diff --git a/composer.lock b/composer.lock index 7acfc83de..304795b45 100644 --- a/composer.lock +++ b/composer.lock @@ -2031,16 +2031,16 @@ }, { "name": "symfony/cache", - "version": "v6.4.2", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978" + "reference": "c88690befb8d4a85dc321fb78d677507f5eb141b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/14a75869bbb41cb35bc5d9d322473928c6f3f978", - "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978", + "url": "https://api.github.com/repos/symfony/cache/zipball/c88690befb8d4a85dc321fb78d677507f5eb141b", + "reference": "c88690befb8d4a85dc321fb78d677507f5eb141b", "shasum": "" }, "require": { @@ -2107,7 +2107,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.2" + "source": "https://github.com/symfony/cache/tree/v6.4.23" }, "funding": [ { @@ -2123,20 +2123,20 @@ "type": "tidelift" } ], - "time": "2023-12-29T15:34:34+00:00" + "time": "2025-06-27T18:31:36+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.4.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "1d74b127da04ffa87aa940abe15446fa89653778" + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1d74b127da04ffa87aa940abe15446fa89653778", - "reference": "1d74b127da04ffa87aa940abe15446fa89653778", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/5d68a57d66910405e5c0b63d6f0af941e66fc868", + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868", "shasum": "" }, "require": { @@ -2145,12 +2145,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -2183,7 +2183,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.6.0" }, "funding": [ { @@ -2199,20 +2199,20 @@ "type": "tidelift" } ], - "time": "2023-09-25T12:52:38+00:00" + "time": "2025-03-13T15:25:07+00:00" }, { "name": "symfony/config", - "version": "v6.4.0", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "5d33e0fb707d603330e0edfd4691803a1253572e" + "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/5d33e0fb707d603330e0edfd4691803a1253572e", - "reference": "5d33e0fb707d603330e0edfd4691803a1253572e", + "url": "https://api.github.com/repos/symfony/config/zipball/af5917a3b1571f54689e56677a3f06440d2fe4c7", + "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7", "shasum": "" }, "require": { @@ -2258,7 +2258,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.4.0" + "source": "https://github.com/symfony/config/tree/v6.4.22" }, "funding": [ { @@ -2274,20 +2274,20 @@ "type": "tidelift" } ], - "time": "2023-11-09T08:28:32+00:00" + "time": "2025-05-14T06:00:01+00:00" }, { "name": "symfony/console", - "version": "v6.4.2", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", + "url": "https://api.github.com/repos/symfony/console/zipball/9056771b8eca08d026cd3280deeec3cfd99c4d93", + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93", "shasum": "" }, "require": { @@ -2352,7 +2352,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.2" + "source": "https://github.com/symfony/console/tree/v6.4.23" }, "funding": [ { @@ -2368,20 +2368,20 @@ "type": "tidelift" } ], - "time": "2023-12-10T16:15:48+00:00" + "time": "2025-06-27T19:37:22+00:00" }, { "name": "symfony/css-selector", - "version": "v6.4.0", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4" + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/d036c6c0d0b09e24a14a35f8292146a658f986e4", - "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/cb23e97813c5837a041b73a6d63a9ddff0778f5e", + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e", "shasum": "" }, "require": { @@ -2417,7 +2417,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.0" + "source": "https://github.com/symfony/css-selector/tree/v6.4.13" }, "funding": [ { @@ -2433,20 +2433,20 @@ "type": "tidelift" } ], - "time": "2023-10-31T08:40:20+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.2", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195" + "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/226ea431b1eda6f0d9f5a4b278757171960bb195", - "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0d9f24f3de0a83573fce5c9ed025d6306c6e166b", + "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b", "shasum": "" }, "require": { @@ -2454,7 +2454,7 @@ "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10|^7.0" + "symfony/var-exporter": "^6.4.20|^7.2.5" }, "conflict": { "ext-psr": "<1.1|>=2", @@ -2498,7 +2498,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.2" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.23" }, "funding": [ { @@ -2514,20 +2514,20 @@ "type": "tidelift" } ], - "time": "2023-12-28T19:16:56+00:00" + "time": "2025-06-23T06:49:06+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -2535,12 +2535,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -2565,7 +2565,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -2581,20 +2581,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/dotenv", - "version": "v6.4.2", + "version": "v6.4.16", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "835f8d2d1022934ac038519de40b88158798c96f" + "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/835f8d2d1022934ac038519de40b88158798c96f", - "reference": "835f8d2d1022934ac038519de40b88158798c96f", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/1ac5e7e7e862d4d574258daf08bd569ba926e4a5", + "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5", "shasum": "" }, "require": { @@ -2639,7 +2639,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.2" + "source": "https://github.com/symfony/dotenv/tree/v6.4.16" }, "funding": [ { @@ -2655,20 +2655,20 @@ "type": "tidelift" } ], - "time": "2023-12-28T19:16:56+00:00" + "time": "2024-11-27T11:08:19+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.0", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788" + "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/c873490a1c97b3a0a4838afc36ff36c112d02788", - "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/b088e0b175c30b4e06d8085200fa465b586f44fa", + "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa", "shasum": "" }, "require": { @@ -2714,7 +2714,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.0" + "source": "https://github.com/symfony/error-handler/tree/v6.4.23" }, "funding": [ { @@ -2730,20 +2730,20 @@ "type": "tidelift" } ], - "time": "2023-10-18T09:43:34+00:00" + "time": "2025-06-13T07:39:48+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.2", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "e95216850555cd55e71b857eb9d6c2674124603a" + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a", - "reference": "e95216850555cd55e71b857eb9d6c2674124603a", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", "shasum": "" }, "require": { @@ -2794,7 +2794,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.2" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.13" }, "funding": [ { @@ -2810,20 +2810,20 @@ "type": "tidelift" } ], - "time": "2023-12-27T22:16:42+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.4.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { @@ -2832,12 +2832,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -2870,7 +2870,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -2886,20 +2886,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.0", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59" + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59", - "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", "shasum": "" }, "require": { @@ -2907,6 +2907,9 @@ "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" + }, "type": "library", "autoload": { "psr-4": { @@ -2933,7 +2936,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.0" + "source": "https://github.com/symfony/filesystem/tree/v6.4.13" }, "funding": [ { @@ -2949,20 +2952,20 @@ "type": "tidelift" } ], - "time": "2023-07-26T17:27:13+00:00" + "time": "2024-10-25T15:07:50+00:00" }, { "name": "symfony/finder", - "version": "v6.4.0", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" + "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", - "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", + "url": "https://api.github.com/repos/symfony/finder/zipball/1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7", + "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7", "shasum": "" }, "require": { @@ -2997,7 +3000,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.0" + "source": "https://github.com/symfony/finder/tree/v6.4.17" }, "funding": [ { @@ -3013,20 +3016,20 @@ "type": "tidelift" } ], - "time": "2023-10-31T17:30:12+00:00" + "time": "2024-12-29T13:51:37+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.4.2", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0" + "reference": "ff892d3ab4b8aa35921bc2120a4b31d57948fe22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c26a221e0462027d1f9d4a802ed63f8ab07a43d0", - "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/ff892d3ab4b8aa35921bc2120a4b31d57948fe22", + "reference": "ff892d3ab4b8aa35921bc2120a4b31d57948fe22", "shasum": "" }, "require": { @@ -3035,7 +3038,7 @@ "php": ">=8.1", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/config": "^6.1|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4.12|^7.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.1|^7.0", "symfony/event-dispatcher": "^5.4|^6.0|^7.0", @@ -3065,7 +3068,8 @@ "symfony/mime": "<6.4", "symfony/property-access": "<5.4", "symfony/property-info": "<5.4", - "symfony/scheduler": "<6.4", + "symfony/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6", + "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/security-core": "<5.4", "symfony/security-csrf": "<5.4", "symfony/serializer": "<6.4", @@ -3104,7 +3108,7 @@ "symfony/process": "^5.4|^6.0|^7.0", "symfony/property-info": "^5.4|^6.0|^7.0", "symfony/rate-limiter": "^5.4|^6.0|^7.0", - "symfony/scheduler": "^6.4|^7.0", + "symfony/scheduler": "^6.4.4|^7.0.4", "symfony/security-bundle": "^5.4|^6.0|^7.0", "symfony/semaphore": "^5.4|^6.0|^7.0", "symfony/serializer": "^6.4|^7.0", @@ -3117,7 +3121,7 @@ "symfony/web-link": "^5.4|^6.0|^7.0", "symfony/workflow": "^6.4|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0", - "twig/twig": "^2.10|^3.0" + "twig/twig": "^2.10|^3.0.4" }, "type": "symfony-bundle", "autoload": { @@ -3145,7 +3149,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.2" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.23" }, "funding": [ { @@ -3161,20 +3165,20 @@ "type": "tidelift" } ], - "time": "2023-12-29T15:34:34+00:00" + "time": "2025-06-26T21:24:02+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.2", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271" + "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/172d807f9ef3fc3fbed8377cc57c20d389269271", - "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/452d19f945ee41345fd8a50c18b60783546b7bd3", + "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3", "shasum": "" }, "require": { @@ -3184,12 +3188,12 @@ "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.3" + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3|^7.0", + "symfony/cache": "^6.4.12|^7.1.5", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", @@ -3222,7 +3226,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.2" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.23" }, "funding": [ { @@ -3238,20 +3242,20 @@ "type": "tidelift" } ], - "time": "2023-12-27T22:16:42+00:00" + "time": "2025-05-26T09:17:58+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.2", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "13e8387320b5942d0dc408440c888e2d526efef4" + "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4", - "reference": "13e8387320b5942d0dc408440c888e2d526efef4", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2bb2cba685aabd859f22cf6946554e8e7f3c329a", + "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a", "shasum": "" }, "require": { @@ -3300,12 +3304,13 @@ "symfony/process": "^5.4|^6.0|^7.0", "symfony/property-access": "^5.4.5|^6.0.5|^7.0", "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.3|^7.0", + "symfony/serializer": "^6.4.4|^7.0.4", "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/translation": "^5.4|^6.0|^7.0", "symfony/translation-contracts": "^2.5|^3", "symfony/uid": "^5.4|^6.0|^7.0", "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.4|^7.0", "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, @@ -3335,7 +3340,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.2" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.23" }, "funding": [ { @@ -3351,24 +3356,24 @@ "type": "tidelift" } ], - "time": "2023-12-30T15:31:44+00:00" + "time": "2025-06-28T08:14:51+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -3378,12 +3383,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3417,7 +3419,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -3433,36 +3435,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3498,7 +3497,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -3514,38 +3513,34 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3585,7 +3580,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" }, "funding": [ { @@ -3601,36 +3596,33 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:30:37+00:00" + "time": "2024-09-10T14:38:51+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3669,7 +3661,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -3685,24 +3677,25 @@ "type": "tidelift" } ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -3712,12 +3705,9 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -3752,7 +3742,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -3768,170 +3758,11 @@ "type": "tidelift" } ], - "time": "2023-07-28T09:04:16+00:00" - }, - { - "name": "symfony/polyfill-php72", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -3987,7 +3818,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0" }, "funding": [ { @@ -4007,30 +3838,26 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.28.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-php80": "^1.14" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4067,7 +3894,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" }, "funding": [ { @@ -4083,20 +3910,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T06:22:46+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/routing", - "version": "v6.4.2", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "98eab13a07fddc85766f1756129c69f207ffbc21" + "reference": "1f5234e8457164a3a0038a4c0a4ba27876a9c670" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21", - "reference": "98eab13a07fddc85766f1756129c69f207ffbc21", + "url": "https://api.github.com/repos/symfony/routing/zipball/1f5234e8457164a3a0038a4c0a4ba27876a9c670", + "reference": "1f5234e8457164a3a0038a4c0a4ba27876a9c670", "shasum": "" }, "require": { @@ -4150,7 +3977,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.2" + "source": "https://github.com/symfony/routing/tree/v6.4.22" }, "funding": [ { @@ -4166,20 +3993,20 @@ "type": "tidelift" } ], - "time": "2023-12-29T15:34:34+00:00" + "time": "2025-04-27T16:08:38+00:00" }, { "name": "symfony/runtime", - "version": "v6.4.0", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "86539231fadfdc7f7e9911d6fa7ed84a606e7d34" + "reference": "ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/86539231fadfdc7f7e9911d6fa7ed84a606e7d34", - "reference": "86539231fadfdc7f7e9911d6fa7ed84a606e7d34", + "url": "https://api.github.com/repos/symfony/runtime/zipball/ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f", + "reference": "ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f", "shasum": "" }, "require": { @@ -4229,7 +4056,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v6.4.0" + "source": "https://github.com/symfony/runtime/tree/v6.4.23" }, "funding": [ { @@ -4245,37 +4072,38 @@ "type": "tidelift" } ], - "time": "2023-10-18T09:43:34+00:00" + "time": "2025-06-13T07:44:14+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.4.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -4311,7 +4139,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -4327,20 +4155,20 @@ "type": "tidelift" } ], - "time": "2023-12-26T14:02:43+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "symfony/string", - "version": "v6.4.2", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "url": "https://api.github.com/repos/symfony/string/zipball/73e2c6966a5aef1d4892873ed5322245295370c6", + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6", "shasum": "" }, "require": { @@ -4397,7 +4225,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.2" + "source": "https://github.com/symfony/string/tree/v6.4.21" }, "funding": [ { @@ -4413,20 +4241,20 @@ "type": "tidelift" } ], - "time": "2023-12-10T16:15:48+00:00" + "time": "2025-04-18T15:23:29+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.4.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", "shasum": "" }, "require": { @@ -4434,12 +4262,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -4475,7 +4303,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" }, "funding": [ { @@ -4491,20 +4319,20 @@ "type": "tidelift" } ], - "time": "2023-07-25T15:08:44+00:00" + "time": "2024-09-27T08:32:26+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.4.0", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf" + "reference": "04ab306a2f2c9dbd46f4363383812954f704af9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf", - "reference": "142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/04ab306a2f2c9dbd46f4363383812954f704af9d", + "reference": "04ab306a2f2c9dbd46f4363383812954f704af9d", "shasum": "" }, "require": { @@ -4535,7 +4363,7 @@ "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/form": "^6.4|^7.0", + "symfony/form": "^6.4.20|^7.2.5", "symfony/html-sanitizer": "^6.1|^7.0", "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -4548,7 +4376,7 @@ "symfony/security-core": "^5.4|^6.0|^7.0", "symfony/security-csrf": "^5.4|^6.0|^7.0", "symfony/security-http": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3", "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/translation": "^6.1|^7.0", "symfony/web-link": "^5.4|^6.0|^7.0", @@ -4584,7 +4412,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.0" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.22" }, "funding": [ { @@ -4600,20 +4428,20 @@ "type": "tidelift" } ], - "time": "2023-11-25T08:25:13+00:00" + "time": "2025-05-16T08:23:44+00:00" }, { "name": "symfony/twig-bundle", - "version": "v6.4.0", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "35d84393e598dfb774e6a2bf49e5229a8a6dbe4c" + "reference": "ef970ed7eb9e547d21628e4c803de0943759cbcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/35d84393e598dfb774e6a2bf49e5229a8a6dbe4c", - "reference": "35d84393e598dfb774e6a2bf49e5229a8a6dbe4c", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/ef970ed7eb9e547d21628e4c803de0943759cbcd", + "reference": "ef970ed7eb9e547d21628e4c803de0943759cbcd", "shasum": "" }, "require": { @@ -4668,7 +4496,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/twig-bundle/tree/v6.4.23" }, "funding": [ { @@ -4684,20 +4512,20 @@ "type": "tidelift" } ], - "time": "2023-11-07T14:57:07+00:00" + "time": "2025-06-20T20:02:07+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.2", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f" + "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", - "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", + "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", "shasum": "" }, "require": { @@ -4753,7 +4581,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.2" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.23" }, "funding": [ { @@ -4769,20 +4597,20 @@ "type": "tidelift" } ], - "time": "2023-12-28T19:16:56+00:00" + "time": "2025-06-27T15:05:27+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.2", + "version": "v6.4.22", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e" + "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5fe9a0021b8d35e67d914716ec8de50716a68e7e", - "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f28cf841f5654955c9f88ceaf4b9dc29571988a9", + "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9", "shasum": "" }, "require": { @@ -4790,6 +4618,8 @@ "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", @@ -4828,7 +4658,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.2" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.22" }, "funding": [ { @@ -4844,20 +4674,20 @@ "type": "tidelift" } ], - "time": "2023-12-27T08:18:35+00:00" + "time": "2025-05-14T13:00:13+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.0", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587" + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4f9237a1bb42455d609e6687d2613dde5b41a587", - "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587", + "url": "https://api.github.com/repos/symfony/yaml/zipball/93e29e0deb5f1b2e360adfb389a20d25eb81a27b", + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b", "shasum": "" }, "require": { @@ -4900,7 +4730,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.0" + "source": "https://github.com/symfony/yaml/tree/v6.4.23" }, "funding": [ { @@ -4916,7 +4746,7 @@ "type": "tidelift" } ], - "time": "2023-11-06T11:00:25+00:00" + "time": "2025-06-03T06:46:12+00:00" }, { "name": "tecnickcom/tcpdf", @@ -5192,16 +5022,16 @@ "packages-dev": [ { "name": "symfony/debug-bundle", - "version": "v6.4.0", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "1e07027423d1d37125b60a50997ada26a9d9d202" + "reference": "7bcfaff39e094cc09455201916d016d9b2ae08ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/1e07027423d1d37125b60a50997ada26a9d9d202", - "reference": "1e07027423d1d37125b60a50997ada26a9d9d202", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/7bcfaff39e094cc09455201916d016d9b2ae08ff", + "reference": "7bcfaff39e094cc09455201916d016d9b2ae08ff", "shasum": "" }, "require": { @@ -5246,7 +5076,7 @@ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/debug-bundle/tree/v6.4.13" }, "funding": [ { @@ -5262,20 +5092,20 @@ "type": "tidelift" } ], - "time": "2023-11-01T12:07:38+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.4.0", + "version": "v6.4.19", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2" + "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", + "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", "shasum": "" }, "require": { @@ -5308,7 +5138,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.0" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.19" }, "funding": [ { @@ -5324,20 +5154,20 @@ "type": "tidelift" } ], - "time": "2023-02-16T10:14:28+00:00" + "time": "2025-02-21T10:06:30+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.2", + "version": "v6.4.19", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2" + "reference": "7d1026a8e950d416cb5148ae88ac23db5d264839" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/38462d16856740ec0d1ba2cb902eebf09100dde2", - "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/7d1026a8e950d416cb5148ae88ac23db5d264839", + "reference": "7d1026a8e950d416cb5148ae88ac23db5d264839", "shasum": "" }, "require": { @@ -5390,7 +5220,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.2" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.19" }, "funding": [ { @@ -5406,12 +5236,12 @@ "type": "tidelift" } ], - "time": "2023-12-27T08:18:35+00:00" + "time": "2025-02-14T12:21:59+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -5424,7 +5254,7 @@ "ext-mysqli": "*", "ext-soap": "*" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.1.0" }, diff --git a/lib/autoload.php b/lib/autoload.php index db10dc867..9ee03077e 100644 --- a/lib/autoload.php +++ b/lib/autoload.php @@ -14,10 +14,7 @@ if (PHP_VERSION_ID < 50600) { echo $err; } } - trigger_error( - $err, - E_USER_ERROR - ); + throw new RuntimeException($err); } require_once __DIR__ . '/composer/autoload_real.php'; diff --git a/lib/bin/patch-type-declarations b/lib/bin/patch-type-declarations old mode 100644 new mode 100755 diff --git a/lib/bin/patch-type-declarations.bat b/lib/bin/patch-type-declarations.bat old mode 100644 new mode 100755 diff --git a/lib/bin/var-dump-server b/lib/bin/var-dump-server old mode 100644 new mode 100755 diff --git a/lib/bin/var-dump-server.bat b/lib/bin/var-dump-server.bat old mode 100644 new mode 100755 diff --git a/lib/bin/yaml-lint b/lib/bin/yaml-lint old mode 100644 new mode 100755 diff --git a/lib/bin/yaml-lint.bat b/lib/bin/yaml-lint.bat old mode 100644 new mode 100755 diff --git a/lib/composer/InstalledVersions.php b/lib/composer/InstalledVersions.php index 6d29bff66..2052022fd 100644 --- a/lib/composer/InstalledVersions.php +++ b/lib/composer/InstalledVersions.php @@ -26,6 +26,12 @@ use Composer\Semver\VersionParser; */ class InstalledVersions { + /** + * @var string|null if set (by reflection by Composer), this should be set to the path where this class is being copied to + * @internal + */ + private static $selfDir = null; + /** * @var mixed[]|null * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null @@ -322,6 +328,18 @@ class InstalledVersions self::$installedIsLocalDir = false; } + /** + * @return string + */ + private static function getSelfDir() + { + if (self::$selfDir === null) { + self::$selfDir = strtr(__DIR__, '\\', '/'); + } + + return self::$selfDir; + } + /** * @return array[] * @psalm-return list}> @@ -336,7 +354,7 @@ class InstalledVersions $copiedLocalDir = false; if (self::$canGetVendors) { - $selfDir = strtr(__DIR__, '\\', '/'); + $selfDir = self::getSelfDir(); foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { $vendorDir = strtr($vendorDir, '\\', '/'); if (isset(self::$installedByVendor[$vendorDir])) { diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index e40ff9a34..22ba90e81 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -28,7 +28,6 @@ return array( 'AsyncSendEmail' => $baseDir . '/core/asynctask.class.inc.php', 'AsyncSendNewsroom' => $baseDir . '/core/asynctask.class.inc.php', 'AsyncTask' => $baseDir . '/core/asynctask.class.inc.php', - 'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'AttributeApplicationLanguage' => $baseDir . '/core/attributedef.class.inc.php', 'AttributeArchiveDate' => $baseDir . '/core/attributedef.class.inc.php', 'AttributeArchiveFlag' => $baseDir . '/core/attributedef.class.inc.php', @@ -1435,7 +1434,6 @@ return array( 'PhpParser\\Parser\\Tokens' => $vendorDir . '/nikic/php-parser/lib/PhpParser/Parser/Tokens.php', 'PhpParser\\PrettyPrinterAbstract' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php', 'PhpParser\\PrettyPrinter\\Standard' => $vendorDir . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php', - 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'PluginInstanciationManager' => $baseDir . '/core/plugininstanciationmanager.class.inc.php', 'PluginManager' => $baseDir . '/core/pluginmanager.class.inc.php', 'PortalDispatcher' => $baseDir . '/application/portaldispatcher.class.inc.php', @@ -1512,6 +1510,7 @@ return array( 'SQLObjectQueryBuilder' => $baseDir . '/core/sqlobjectquerybuilder.class.inc.php', 'SQLQuery' => $baseDir . '/core/sqlquery.class.inc.php', 'SQLUnionQuery' => $baseDir . '/core/sqlunionquery.class.inc.php', + 'SQLite3Exception' => $vendorDir . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'SVGDOMSanitizer' => $baseDir . '/core/htmlsanitizer.class.inc.php', 'Sabberworm\\CSS\\CSSList\\AtRuleBlockList' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php', 'Sabberworm\\CSS\\CSSList\\CSSBlockList' => $vendorDir . '/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php', @@ -1628,7 +1627,6 @@ return array( 'StimulusInternal' => $baseDir . '/core/stimulus.class.inc.php', 'StimulusUserAction' => $baseDir . '/core/stimulus.class.inc.php', 'Str' => $baseDir . '/core/MyHelpers.class.inc.php', - 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Bridge\\Twig\\AppVariable' => $vendorDir . '/symfony/twig-bridge/AppVariable.php', 'Symfony\\Bridge\\Twig\\Attribute\\Template' => $vendorDir . '/symfony/twig-bridge/Attribute/Template.php', 'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => $vendorDir . '/symfony/twig-bridge/Command/DebugCommand.php', @@ -1752,6 +1750,7 @@ return array( 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\RemoveUnusedSessionMarshallingHandlerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerRealRefPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerWeakRefPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php', + 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TranslationUpdateCommandPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\UnusedTagsPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\WorkflowGuardListenerPass' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/framework-bundle/DependencyInjection/Configuration.php', @@ -1859,13 +1858,24 @@ return array( 'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => $vendorDir . '/symfony/cache/Traits/ProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => $vendorDir . '/symfony/cache/Traits/Redis5Proxy.php', 'Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => $vendorDir . '/symfony/cache/Traits/Redis6Proxy.php', + 'Symfony\\Component\\Cache\\Traits\\Redis6ProxyTrait' => $vendorDir . '/symfony/cache/Traits/Redis6ProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster5Proxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => $vendorDir . '/symfony/cache/Traits/RedisCluster6Proxy.php', + 'Symfony\\Component\\Cache\\Traits\\RedisCluster6ProxyTrait' => $vendorDir . '/symfony/cache/Traits/RedisCluster6ProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterNodeProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => $vendorDir . '/symfony/cache/Traits/RedisClusterProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisProxy' => $vendorDir . '/symfony/cache/Traits/RedisProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisTrait' => $vendorDir . '/symfony/cache/Traits/RedisTrait.php', 'Symfony\\Component\\Cache\\Traits\\RelayProxy' => $vendorDir . '/symfony/cache/Traits/RelayProxy.php', + 'Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => $vendorDir . '/symfony/cache/Traits/RelayProxyTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\BgsaveTrait' => $vendorDir . '/symfony/cache/Traits/Relay/BgsaveTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\CopyTrait' => $vendorDir . '/symfony/cache/Traits/Relay/CopyTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\GeosearchTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GeosearchTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\GetrangeTrait' => $vendorDir . '/symfony/cache/Traits/Relay/GetrangeTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\HsetTrait' => $vendorDir . '/symfony/cache/Traits/Relay/HsetTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\MoveTrait' => $vendorDir . '/symfony/cache/Traits/Relay/MoveTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\NullableReturnTrait' => $vendorDir . '/symfony/cache/Traits/Relay/NullableReturnTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\PfcountTrait' => $vendorDir . '/symfony/cache/Traits/Relay/PfcountTrait.php', 'Symfony\\Component\\Config\\Builder\\ClassBuilder' => $vendorDir . '/symfony/config/Builder/ClassBuilder.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGenerator.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php', @@ -2609,6 +2619,7 @@ return array( 'Symfony\\Component\\HttpKernel\\Fragment\\RoutableFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php', 'Symfony\\Component\\HttpKernel\\Fragment\\SsiFragmentRenderer' => $vendorDir . '/symfony/http-kernel/Fragment/SsiFragmentRenderer.php', 'Symfony\\Component\\HttpKernel\\HttpCache\\AbstractSurrogate' => $vendorDir . '/symfony/http-kernel/HttpCache/AbstractSurrogate.php', + 'Symfony\\Component\\HttpKernel\\HttpCache\\CacheWasLockedException' => $vendorDir . '/symfony/http-kernel/HttpCache/CacheWasLockedException.php', 'Symfony\\Component\\HttpKernel\\HttpCache\\Esi' => $vendorDir . '/symfony/http-kernel/HttpCache/Esi.php', 'Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache' => $vendorDir . '/symfony/http-kernel/HttpCache/HttpCache.php', 'Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategy' => $vendorDir . '/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php', @@ -2784,6 +2795,7 @@ return array( 'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => $vendorDir . '/symfony/var-dumper/Cloner/Cursor.php', 'Symfony\\Component\\VarDumper\\Cloner\\Data' => $vendorDir . '/symfony/var-dumper/Cloner/Data.php', 'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => $vendorDir . '/symfony/var-dumper/Cloner/DumperInterface.php', + 'Symfony\\Component\\VarDumper\\Cloner\\Internal\\NoDefault' => $vendorDir . '/symfony/var-dumper/Cloner/Internal/NoDefault.php', 'Symfony\\Component\\VarDumper\\Cloner\\Stub' => $vendorDir . '/symfony/var-dumper/Cloner/Stub.php', 'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => $vendorDir . '/symfony/var-dumper/Cloner/VarCloner.php', 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => $vendorDir . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', @@ -2839,13 +2851,16 @@ return array( 'Symfony\\Contracts\\Cache\\CacheTrait' => $vendorDir . '/symfony/cache-contracts/CacheTrait.php', 'Symfony\\Contracts\\Cache\\CallbackInterface' => $vendorDir . '/symfony/cache-contracts/CallbackInterface.php', 'Symfony\\Contracts\\Cache\\ItemInterface' => $vendorDir . '/symfony/cache-contracts/ItemInterface.php', + 'Symfony\\Contracts\\Cache\\NamespacedPoolInterface' => $vendorDir . '/symfony/cache-contracts/NamespacedPoolInterface.php', 'Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => $vendorDir . '/symfony/cache-contracts/TagAwareCacheInterface.php', 'Symfony\\Contracts\\EventDispatcher\\Event' => $vendorDir . '/symfony/event-dispatcher-contracts/Event.php', 'Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => $vendorDir . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php', 'Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/symfony/service-contracts/Attribute/Required.php', 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/symfony/service-contracts/Attribute/SubscribedService.php', 'Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/symfony/service-contracts/ResetInterface.php', + 'Symfony\\Contracts\\Service\\ServiceCollectionInterface' => $vendorDir . '/symfony/service-contracts/ServiceCollectionInterface.php', 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/symfony/service-contracts/ServiceLocatorTrait.php', + 'Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php', 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/symfony/service-contracts/ServiceProviderInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/symfony/service-contracts/ServiceSubscriberTrait.php', @@ -2861,9 +2876,6 @@ return array( 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => $vendorDir . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php', 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php', - 'Symfony\\Polyfill\\Php72\\Php72' => $vendorDir . '/symfony/polyfill-php72/Php72.php', - 'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/symfony/polyfill-php80/Php80.php', - 'Symfony\\Polyfill\\Php80\\PhpToken' => $vendorDir . '/symfony/polyfill-php80/PhpToken.php', 'Symfony\\Polyfill\\Php81\\Php81' => $vendorDir . '/symfony/polyfill-php81/Php81.php', 'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php', 'Symfony\\Runtime\\Symfony\\Component\\Console\\ApplicationRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/ApplicationRuntime.php', @@ -3129,7 +3141,6 @@ return array( 'URLButtonItem' => $baseDir . '/application/applicationextension.inc.php', 'URLPopupMenuItem' => $baseDir . '/application/applicationextension.inc.php', 'UnaryExpression' => $baseDir . '/core/oql/expression.class.inc.php', - 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'UnknownClassOqlException' => $baseDir . '/core/oql/oqlinterpreter.class.inc.php', 'User' => $baseDir . '/core/userrights.class.inc.php', 'UserDashboard' => $baseDir . '/application/user.dashboard.class.inc.php', @@ -3137,7 +3148,6 @@ return array( 'UserRightException' => $baseDir . '/application/exceptions/UserRightException.php', 'UserRights' => $baseDir . '/core/userrights.class.inc.php', 'UserRightsAddOnAPI' => $baseDir . '/core/userrights.class.inc.php', - 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 'ValueSetDefinition' => $baseDir . '/core/valuesetdef.class.inc.php', 'ValueSetEnum' => $baseDir . '/core/valuesetdef.class.inc.php', 'ValueSetEnumClasses' => $baseDir . '/core/valuesetdef.class.inc.php', diff --git a/lib/composer/autoload_files.php b/lib/composer/autoload_files.php index b3a813be2..42c6b5283 100644 --- a/lib/composer/autoload_files.php +++ b/lib/composer/autoload_files.php @@ -9,7 +9,6 @@ return array( '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', - 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php', '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', '23c18046f52bef3eea034657bafda50f' => $vendorDir . '/symfony/polyfill-php81/bootstrap.php', @@ -22,7 +21,6 @@ return array( '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', 'c9d07b32a2e02bc0fc582d4f0c1b56cc' => $vendorDir . '/laminas/laminas-servicemanager/src/autoload.php', '8825ede83f2f289127722d4e842cf7e8' => $vendorDir . '/symfony/polyfill-intl-grapheme/bootstrap.php', - '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => $vendorDir . '/symfony/string/Resources/functions.php', '344f11dc3484aaed5cbde58e23513be4' => $vendorDir . '/apereo/phpcas/source/CAS.php', diff --git a/lib/composer/autoload_psr4.php b/lib/composer/autoload_psr4.php index 7b7ab3646..18f7002d4 100644 --- a/lib/composer/autoload_psr4.php +++ b/lib/composer/autoload_psr4.php @@ -12,8 +12,6 @@ return array( 'Symfony\\Runtime\\Symfony\\Component\\' => array($vendorDir . '/symfony/runtime/Internal'), 'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'), 'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'), - 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), - 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index fb8df03ef..ebc0841a9 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -10,7 +10,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', - 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php', '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', '23c18046f52bef3eea034657bafda50f' => __DIR__ . '/..' . '/symfony/polyfill-php81/bootstrap.php', @@ -23,7 +22,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', 'c9d07b32a2e02bc0fc582d4f0c1b56cc' => __DIR__ . '/..' . '/laminas/laminas-servicemanager/src/autoload.php', '8825ede83f2f289127722d4e842cf7e8' => __DIR__ . '/..' . '/symfony/polyfill-intl-grapheme/bootstrap.php', - '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', 'b6b991a57620e2fb6b2f66f03fe9ddc2' => __DIR__ . '/..' . '/symfony/string/Resources/functions.php', '344f11dc3484aaed5cbde58e23513be4' => __DIR__ . '/..' . '/apereo/phpcas/source/CAS.php', @@ -45,8 +43,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Runtime\\Symfony\\Component\\' => 34, 'Symfony\\Polyfill\\Php83\\' => 23, 'Symfony\\Polyfill\\Php81\\' => 23, - 'Symfony\\Polyfill\\Php80\\' => 23, - 'Symfony\\Polyfill\\Php72\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, 'Symfony\\Polyfill\\Intl\\Idn\\' => 26, @@ -142,14 +138,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php81', ), - 'Symfony\\Polyfill\\Php80\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', - ), - 'Symfony\\Polyfill\\Php72\\' => - array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', - ), 'Symfony\\Polyfill\\Mbstring\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', @@ -418,7 +406,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'AsyncSendEmail' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', 'AsyncSendNewsroom' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', 'AsyncTask' => __DIR__ . '/../..' . '/core/asynctask.class.inc.php', - 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 'AttributeApplicationLanguage' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', 'AttributeArchiveDate' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', 'AttributeArchiveFlag' => __DIR__ . '/../..' . '/core/attributedef.class.inc.php', @@ -1825,7 +1812,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'PhpParser\\Parser\\Tokens' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/Parser/Tokens.php', 'PhpParser\\PrettyPrinterAbstract' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php', 'PhpParser\\PrettyPrinter\\Standard' => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php', - 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 'PluginInstanciationManager' => __DIR__ . '/../..' . '/core/plugininstanciationmanager.class.inc.php', 'PluginManager' => __DIR__ . '/../..' . '/core/pluginmanager.class.inc.php', 'PortalDispatcher' => __DIR__ . '/../..' . '/application/portaldispatcher.class.inc.php', @@ -1902,6 +1888,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'SQLObjectQueryBuilder' => __DIR__ . '/../..' . '/core/sqlobjectquerybuilder.class.inc.php', 'SQLQuery' => __DIR__ . '/../..' . '/core/sqlquery.class.inc.php', 'SQLUnionQuery' => __DIR__ . '/../..' . '/core/sqlunionquery.class.inc.php', + 'SQLite3Exception' => __DIR__ . '/..' . '/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', 'SVGDOMSanitizer' => __DIR__ . '/../..' . '/core/htmlsanitizer.class.inc.php', 'Sabberworm\\CSS\\CSSList\\AtRuleBlockList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php', 'Sabberworm\\CSS\\CSSList\\CSSBlockList' => __DIR__ . '/..' . '/sabberworm/php-css-parser/src/CSSList/CSSBlockList.php', @@ -2018,7 +2005,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'StimulusInternal' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php', 'StimulusUserAction' => __DIR__ . '/../..' . '/core/stimulus.class.inc.php', 'Str' => __DIR__ . '/../..' . '/core/MyHelpers.class.inc.php', - 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 'Symfony\\Bridge\\Twig\\AppVariable' => __DIR__ . '/..' . '/symfony/twig-bridge/AppVariable.php', 'Symfony\\Bridge\\Twig\\Attribute\\Template' => __DIR__ . '/..' . '/symfony/twig-bridge/Attribute/Template.php', 'Symfony\\Bridge\\Twig\\Command\\DebugCommand' => __DIR__ . '/..' . '/symfony/twig-bridge/Command/DebugCommand.php', @@ -2142,6 +2128,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\RemoveUnusedSessionMarshallingHandlerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/RemoveUnusedSessionMarshallingHandlerPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerRealRefPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerRealRefPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TestServiceContainerWeakRefPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TestServiceContainerWeakRefPass.php', + 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\TranslationUpdateCommandPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\UnusedTagsPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/UnusedTagsPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Compiler\\WorkflowGuardListenerPass' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php', 'Symfony\\Bundle\\FrameworkBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/framework-bundle/DependencyInjection/Configuration.php', @@ -2249,13 +2236,24 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\Cache\\Traits\\ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/ProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\Redis5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis5Proxy.php', 'Symfony\\Component\\Cache\\Traits\\Redis6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis6Proxy.php', + 'Symfony\\Component\\Cache\\Traits\\Redis6ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Redis6ProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\RedisCluster5Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster5Proxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisCluster6Proxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster6Proxy.php', + 'Symfony\\Component\\Cache\\Traits\\RedisCluster6ProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisCluster6ProxyTrait.php', 'Symfony\\Component\\Cache\\Traits\\RedisClusterNodeProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterNodeProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisClusterProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisClusterProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisProxy.php', 'Symfony\\Component\\Cache\\Traits\\RedisTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RedisTrait.php', 'Symfony\\Component\\Cache\\Traits\\RelayProxy' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxy.php', + 'Symfony\\Component\\Cache\\Traits\\RelayProxyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/RelayProxyTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\BgsaveTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/BgsaveTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\CopyTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/CopyTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\GeosearchTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GeosearchTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\GetrangeTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/GetrangeTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\HsetTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/HsetTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\MoveTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/MoveTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\NullableReturnTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/NullableReturnTrait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\PfcountTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/PfcountTrait.php', 'Symfony\\Component\\Config\\Builder\\ClassBuilder' => __DIR__ . '/..' . '/symfony/config/Builder/ClassBuilder.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGenerator.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGeneratorInterface' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGeneratorInterface.php', @@ -2999,6 +2997,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\HttpKernel\\Fragment\\RoutableFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php', 'Symfony\\Component\\HttpKernel\\Fragment\\SsiFragmentRenderer' => __DIR__ . '/..' . '/symfony/http-kernel/Fragment/SsiFragmentRenderer.php', 'Symfony\\Component\\HttpKernel\\HttpCache\\AbstractSurrogate' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/AbstractSurrogate.php', + 'Symfony\\Component\\HttpKernel\\HttpCache\\CacheWasLockedException' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/CacheWasLockedException.php', 'Symfony\\Component\\HttpKernel\\HttpCache\\Esi' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/Esi.php', 'Symfony\\Component\\HttpKernel\\HttpCache\\HttpCache' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/HttpCache.php', 'Symfony\\Component\\HttpKernel\\HttpCache\\ResponseCacheStrategy' => __DIR__ . '/..' . '/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php', @@ -3174,6 +3173,7 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Component\\VarDumper\\Cloner\\Cursor' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Cursor.php', 'Symfony\\Component\\VarDumper\\Cloner\\Data' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Data.php', 'Symfony\\Component\\VarDumper\\Cloner\\DumperInterface' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/DumperInterface.php', + 'Symfony\\Component\\VarDumper\\Cloner\\Internal\\NoDefault' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Internal/NoDefault.php', 'Symfony\\Component\\VarDumper\\Cloner\\Stub' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/Stub.php', 'Symfony\\Component\\VarDumper\\Cloner\\VarCloner' => __DIR__ . '/..' . '/symfony/var-dumper/Cloner/VarCloner.php', 'Symfony\\Component\\VarDumper\\Command\\Descriptor\\CliDescriptor' => __DIR__ . '/..' . '/symfony/var-dumper/Command/Descriptor/CliDescriptor.php', @@ -3229,13 +3229,16 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Contracts\\Cache\\CacheTrait' => __DIR__ . '/..' . '/symfony/cache-contracts/CacheTrait.php', 'Symfony\\Contracts\\Cache\\CallbackInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/CallbackInterface.php', 'Symfony\\Contracts\\Cache\\ItemInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/ItemInterface.php', + 'Symfony\\Contracts\\Cache\\NamespacedPoolInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/NamespacedPoolInterface.php', 'Symfony\\Contracts\\Cache\\TagAwareCacheInterface' => __DIR__ . '/..' . '/symfony/cache-contracts/TagAwareCacheInterface.php', 'Symfony\\Contracts\\EventDispatcher\\Event' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/Event.php', 'Symfony\\Contracts\\EventDispatcher\\EventDispatcherInterface' => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts/EventDispatcherInterface.php', 'Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/Required.php', 'Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/symfony/service-contracts/Attribute/SubscribedService.php', 'Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ResetInterface.php', + 'Symfony\\Contracts\\Service\\ServiceCollectionInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceCollectionInterface.php', 'Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceLocatorTrait.php', + 'Symfony\\Contracts\\Service\\ServiceMethodsSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceMethodsSubscriberTrait.php', 'Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceProviderInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberInterface.php', 'Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/symfony/service-contracts/ServiceSubscriberTrait.php', @@ -3251,9 +3254,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'Symfony\\Polyfill\\Intl\\Idn\\Resources\\unidata\\Regex' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Resources/unidata/Regex.php', 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php', - 'Symfony\\Polyfill\\Php72\\Php72' => __DIR__ . '/..' . '/symfony/polyfill-php72/Php72.php', - 'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/symfony/polyfill-php80/Php80.php', - 'Symfony\\Polyfill\\Php80\\PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/PhpToken.php', 'Symfony\\Polyfill\\Php81\\Php81' => __DIR__ . '/..' . '/symfony/polyfill-php81/Php81.php', 'Symfony\\Polyfill\\Php83\\Php83' => __DIR__ . '/..' . '/symfony/polyfill-php83/Php83.php', 'Symfony\\Runtime\\Symfony\\Component\\Console\\ApplicationRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/ApplicationRuntime.php', @@ -3519,7 +3519,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'URLButtonItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'URLPopupMenuItem' => __DIR__ . '/../..' . '/application/applicationextension.inc.php', 'UnaryExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', - 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 'UnknownClassOqlException' => __DIR__ . '/../..' . '/core/oql/oqlinterpreter.class.inc.php', 'User' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', 'UserDashboard' => __DIR__ . '/../..' . '/application/user.dashboard.class.inc.php', @@ -3527,7 +3526,6 @@ class ComposerStaticInit7f81b4a2a468a061c306af5e447a9a9f 'UserRightException' => __DIR__ . '/../..' . '/application/exceptions/UserRightException.php', 'UserRights' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', 'UserRightsAddOnAPI' => __DIR__ . '/../..' . '/core/userrights.class.inc.php', - 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 'ValueSetDefinition' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', 'ValueSetEnum' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', 'ValueSetEnumClasses' => __DIR__ . '/../..' . '/core/valuesetdef.class.inc.php', diff --git a/lib/composer/installed.json b/lib/composer/installed.json index 274f34f90..15bcd0e12 100644 --- a/lib/composer/installed.json +++ b/lib/composer/installed.json @@ -2118,17 +2118,17 @@ }, { "name": "symfony/cache", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978" + "reference": "c88690befb8d4a85dc321fb78d677507f5eb141b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/14a75869bbb41cb35bc5d9d322473928c6f3f978", - "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978", + "url": "https://api.github.com/repos/symfony/cache/zipball/c88690befb8d4a85dc321fb78d677507f5eb141b", + "reference": "c88690befb8d4a85dc321fb78d677507f5eb141b", "shasum": "" }, "require": { @@ -2162,7 +2162,7 @@ "symfony/messenger": "^5.4|^6.0|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2023-12-29T15:34:34+00:00", + "time": "2025-06-27T18:31:36+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2197,7 +2197,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.2" + "source": "https://github.com/symfony/cache/tree/v6.4.23" }, "funding": [ { @@ -2217,32 +2217,32 @@ }, { "name": "symfony/cache-contracts", - "version": "v3.4.0", - "version_normalized": "3.4.0.0", + "version": "v3.6.0", + "version_normalized": "3.6.0.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "1d74b127da04ffa87aa940abe15446fa89653778" + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1d74b127da04ffa87aa940abe15446fa89653778", - "reference": "1d74b127da04ffa87aa940abe15446fa89653778", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/5d68a57d66910405e5c0b63d6f0af941e66fc868", + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868", "shasum": "" }, "require": { "php": ">=8.1", "psr/cache": "^3.0" }, - "time": "2023-09-25T12:52:38+00:00", + "time": "2025-03-13T15:25:07+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "installation-source": "dist", @@ -2276,7 +2276,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.6.0" }, "funding": [ { @@ -2296,17 +2296,17 @@ }, { "name": "symfony/config", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.22", + "version_normalized": "6.4.22.0", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "5d33e0fb707d603330e0edfd4691803a1253572e" + "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/5d33e0fb707d603330e0edfd4691803a1253572e", - "reference": "5d33e0fb707d603330e0edfd4691803a1253572e", + "url": "https://api.github.com/repos/symfony/config/zipball/af5917a3b1571f54689e56677a3f06440d2fe4c7", + "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7", "shasum": "" }, "require": { @@ -2326,7 +2326,7 @@ "symfony/service-contracts": "^2.5|^3", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2023-11-09T08:28:32+00:00", + "time": "2025-05-14T06:00:01+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2354,7 +2354,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.4.0" + "source": "https://github.com/symfony/config/tree/v6.4.22" }, "funding": [ { @@ -2374,17 +2374,17 @@ }, { "name": "symfony/console", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", + "url": "https://api.github.com/repos/symfony/console/zipball/9056771b8eca08d026cd3280deeec3cfd99c4d93", + "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93", "shasum": "" }, "require": { @@ -2417,7 +2417,7 @@ "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2023-12-10T16:15:48+00:00", + "time": "2025-06-27T19:37:22+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2451,7 +2451,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.2" + "source": "https://github.com/symfony/console/tree/v6.4.23" }, "funding": [ { @@ -2471,23 +2471,23 @@ }, { "name": "symfony/css-selector", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.13", + "version_normalized": "6.4.13.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4" + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/d036c6c0d0b09e24a14a35f8292146a658f986e4", - "reference": "d036c6c0d0b09e24a14a35f8292146a658f986e4", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/cb23e97813c5837a041b73a6d63a9ddff0778f5e", + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e", "shasum": "" }, "require": { "php": ">=8.1" }, - "time": "2023-10-31T08:40:20+00:00", + "time": "2024-09-25T14:18:03+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2519,7 +2519,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.0" + "source": "https://github.com/symfony/css-selector/tree/v6.4.13" }, "funding": [ { @@ -2539,17 +2539,17 @@ }, { "name": "symfony/debug-bundle", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.13", + "version_normalized": "6.4.13.0", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "1e07027423d1d37125b60a50997ada26a9d9d202" + "reference": "7bcfaff39e094cc09455201916d016d9b2ae08ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/1e07027423d1d37125b60a50997ada26a9d9d202", - "reference": "1e07027423d1d37125b60a50997ada26a9d9d202", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/7bcfaff39e094cc09455201916d016d9b2ae08ff", + "reference": "7bcfaff39e094cc09455201916d016d9b2ae08ff", "shasum": "" }, "require": { @@ -2568,7 +2568,7 @@ "symfony/config": "^5.4|^6.0|^7.0", "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" }, - "time": "2023-11-01T12:07:38+00:00", + "time": "2024-09-25T14:18:03+00:00", "type": "symfony-bundle", "installation-source": "dist", "autoload": { @@ -2596,7 +2596,7 @@ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/debug-bundle/tree/v6.4.13" }, "funding": [ { @@ -2616,17 +2616,17 @@ }, { "name": "symfony/dependency-injection", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195" + "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/226ea431b1eda6f0d9f5a4b278757171960bb195", - "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0d9f24f3de0a83573fce5c9ed025d6306c6e166b", + "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b", "shasum": "" }, "require": { @@ -2634,7 +2634,7 @@ "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10|^7.0" + "symfony/var-exporter": "^6.4.20|^7.2.5" }, "conflict": { "ext-psr": "<1.1|>=2", @@ -2652,7 +2652,7 @@ "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2023-12-28T19:16:56+00:00", + "time": "2025-06-23T06:49:06+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2680,7 +2680,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.2" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.23" }, "funding": [ { @@ -2700,31 +2700,31 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.4.0", - "version_normalized": "3.4.0.0", + "version": "v3.6.0", + "version_normalized": "3.6.0.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", - "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { "php": ">=8.1" }, - "time": "2023-05-23T14:45:45+00:00", + "time": "2024-09-25T14:21:43+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "installation-source": "dist", @@ -2750,7 +2750,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -2770,17 +2770,17 @@ }, { "name": "symfony/dotenv", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.16", + "version_normalized": "6.4.16.0", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "835f8d2d1022934ac038519de40b88158798c96f" + "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/835f8d2d1022934ac038519de40b88158798c96f", - "reference": "835f8d2d1022934ac038519de40b88158798c96f", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/1ac5e7e7e862d4d574258daf08bd569ba926e4a5", + "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5", "shasum": "" }, "require": { @@ -2794,7 +2794,7 @@ "symfony/console": "^5.4|^6.0|^7.0", "symfony/process": "^5.4|^6.0|^7.0" }, - "time": "2023-12-28T19:16:56+00:00", + "time": "2024-11-27T11:08:19+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2827,7 +2827,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.2" + "source": "https://github.com/symfony/dotenv/tree/v6.4.16" }, "funding": [ { @@ -2847,17 +2847,17 @@ }, { "name": "symfony/error-handler", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788" + "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/c873490a1c97b3a0a4838afc36ff36c112d02788", - "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/b088e0b175c30b4e06d8085200fa465b586f44fa", + "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa", "shasum": "" }, "require": { @@ -2874,7 +2874,7 @@ "symfony/http-kernel": "^6.4|^7.0", "symfony/serializer": "^5.4|^6.0|^7.0" }, - "time": "2023-10-18T09:43:34+00:00", + "time": "2025-06-13T07:39:48+00:00", "bin": [ "Resources/bin/patch-type-declarations" ], @@ -2905,7 +2905,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.0" + "source": "https://github.com/symfony/error-handler/tree/v6.4.23" }, "funding": [ { @@ -2925,17 +2925,17 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.13", + "version_normalized": "6.4.13.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "e95216850555cd55e71b857eb9d6c2674124603a" + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a", - "reference": "e95216850555cd55e71b857eb9d6c2674124603a", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", "shasum": "" }, "require": { @@ -2960,7 +2960,7 @@ "symfony/service-contracts": "^2.5|^3", "symfony/stopwatch": "^5.4|^6.0|^7.0" }, - "time": "2023-12-27T22:16:42+00:00", + "time": "2024-09-25T14:18:03+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2988,7 +2988,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.2" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.13" }, "funding": [ { @@ -3008,32 +3008,32 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.4.0", - "version_normalized": "3.4.0.0", + "version": "v3.6.0", + "version_normalized": "3.6.0.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", - "reference": "a76aed96a42d2b521153fb382d418e30d18b59df", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { "php": ">=8.1", "psr/event-dispatcher": "^1" }, - "time": "2023-05-23T14:45:45+00:00", + "time": "2024-09-25T14:21:43+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "installation-source": "dist", @@ -3067,7 +3067,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -3087,17 +3087,17 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.13", + "version_normalized": "6.4.13.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59" + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59", - "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", "shasum": "" }, "require": { @@ -3105,7 +3105,10 @@ "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, - "time": "2023-07-26T17:27:13+00:00", + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" + }, + "time": "2024-10-25T15:07:50+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3133,7 +3136,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.0" + "source": "https://github.com/symfony/filesystem/tree/v6.4.13" }, "funding": [ { @@ -3153,17 +3156,17 @@ }, { "name": "symfony/finder", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.17", + "version_normalized": "6.4.17.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" + "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", - "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", + "url": "https://api.github.com/repos/symfony/finder/zipball/1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7", + "reference": "1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7", "shasum": "" }, "require": { @@ -3172,7 +3175,7 @@ "require-dev": { "symfony/filesystem": "^6.0|^7.0" }, - "time": "2023-10-31T17:30:12+00:00", + "time": "2024-12-29T13:51:37+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3200,7 +3203,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.0" + "source": "https://github.com/symfony/finder/tree/v6.4.17" }, "funding": [ { @@ -3220,17 +3223,17 @@ }, { "name": "symfony/framework-bundle", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0" + "reference": "ff892d3ab4b8aa35921bc2120a4b31d57948fe22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c26a221e0462027d1f9d4a802ed63f8ab07a43d0", - "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/ff892d3ab4b8aa35921bc2120a4b31d57948fe22", + "reference": "ff892d3ab4b8aa35921bc2120a4b31d57948fe22", "shasum": "" }, "require": { @@ -3239,7 +3242,7 @@ "php": ">=8.1", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/config": "^6.1|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4.12|^7.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.1|^7.0", "symfony/event-dispatcher": "^5.4|^6.0|^7.0", @@ -3269,7 +3272,8 @@ "symfony/mime": "<6.4", "symfony/property-access": "<5.4", "symfony/property-info": "<5.4", - "symfony/scheduler": "<6.4", + "symfony/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6", + "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/security-core": "<5.4", "symfony/security-csrf": "<5.4", "symfony/serializer": "<6.4", @@ -3308,7 +3312,7 @@ "symfony/process": "^5.4|^6.0|^7.0", "symfony/property-info": "^5.4|^6.0|^7.0", "symfony/rate-limiter": "^5.4|^6.0|^7.0", - "symfony/scheduler": "^6.4|^7.0", + "symfony/scheduler": "^6.4.4|^7.0.4", "symfony/security-bundle": "^5.4|^6.0|^7.0", "symfony/semaphore": "^5.4|^6.0|^7.0", "symfony/serializer": "^6.4|^7.0", @@ -3321,9 +3325,9 @@ "symfony/web-link": "^5.4|^6.0|^7.0", "symfony/workflow": "^6.4|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0", - "twig/twig": "^2.10|^3.0" + "twig/twig": "^2.10|^3.0.4" }, - "time": "2023-12-29T15:34:34+00:00", + "time": "2025-06-26T21:24:02+00:00", "type": "symfony-bundle", "installation-source": "dist", "autoload": { @@ -3351,7 +3355,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.2" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.23" }, "funding": [ { @@ -3371,17 +3375,17 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271" + "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/172d807f9ef3fc3fbed8377cc57c20d389269271", - "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/452d19f945ee41345fd8a50c18b60783546b7bd3", + "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3", "shasum": "" }, "require": { @@ -3391,19 +3395,19 @@ "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.3" + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3|^7.0", + "symfony/cache": "^6.4.12|^7.1.5", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", "symfony/mime": "^5.4|^6.0|^7.0", "symfony/rate-limiter": "^5.4|^6.0|^7.0" }, - "time": "2023-12-27T22:16:42+00:00", + "time": "2025-05-26T09:17:58+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3431,7 +3435,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.2" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.23" }, "funding": [ { @@ -3451,17 +3455,17 @@ }, { "name": "symfony/http-kernel", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "13e8387320b5942d0dc408440c888e2d526efef4" + "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4", - "reference": "13e8387320b5942d0dc408440c888e2d526efef4", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2bb2cba685aabd859f22cf6946554e8e7f3c329a", + "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a", "shasum": "" }, "require": { @@ -3510,16 +3514,17 @@ "symfony/process": "^5.4|^6.0|^7.0", "symfony/property-access": "^5.4.5|^6.0.5|^7.0", "symfony/routing": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.3|^7.0", + "symfony/serializer": "^6.4.4|^7.0.4", "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/translation": "^5.4|^6.0|^7.0", "symfony/translation-contracts": "^2.5|^3", "symfony/uid": "^5.4|^6.0|^7.0", "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^5.4|^6.4|^7.0", "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "time": "2023-12-30T15:31:44+00:00", + "time": "2025-06-28T08:14:51+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3547,7 +3552,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.2" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.23" }, "funding": [ { @@ -3567,21 +3572,21 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "provide": { "ext-ctype": "*" @@ -3589,15 +3594,12 @@ "suggest": { "ext-ctype": "For best performance" }, - "time": "2023-01-26T09:26:14+00:00", + "time": "2024-09-09T11:45:10+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "installation-source": "dist", @@ -3632,7 +3634,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { @@ -3652,34 +3654,31 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, - "time": "2023-01-26T09:26:14+00:00", + "time": "2024-09-09T11:45:10+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "installation-source": "dist", @@ -3716,7 +3715,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -3736,36 +3735,32 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", - "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-intl-normalizer": "^1.10", - "symfony/polyfill-php72": "^1.10" + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" }, "suggest": { "ext-intl": "For best performance" }, - "time": "2023-01-26T09:30:37+00:00", + "time": "2024-09-10T14:38:51+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "installation-source": "dist", @@ -3806,7 +3801,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" }, "funding": [ { @@ -3826,34 +3821,31 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "suggest": { "ext-intl": "For best performance" }, - "time": "2023-01-26T09:26:14+00:00", + "time": "2024-09-09T11:45:10+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "installation-source": "dist", @@ -3893,7 +3885,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -3913,21 +3905,22 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "42292d99c55abe617799667f454222c54c60e229" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", - "reference": "42292d99c55abe617799667f454222c54c60e229", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=7.1" + "ext-iconv": "*", + "php": ">=7.2" }, "provide": { "ext-mbstring": "*" @@ -3935,15 +3928,12 @@ "suggest": { "ext-mbstring": "For best performance" }, - "time": "2023-07-28T09:04:16+00:00", + "time": "2024-12-23T08:48:59+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "installation-source": "dist", @@ -3979,7 +3969,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -3997,175 +3987,10 @@ ], "install-path": "../symfony/polyfill-mbstring" }, - { - "name": "symfony/polyfill-php72", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", - "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2023-01-26T09:26:14+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php72\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-php72" - }, - { - "name": "symfony/polyfill-php80", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "time": "2023-01-26T09:26:14+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "installation-source": "dist", - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "install-path": "../symfony/polyfill-php80" - }, { "name": "symfony/polyfill-php81", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -4223,7 +4048,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0" }, "funding": [ { @@ -4243,32 +4068,28 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.28.0", - "version_normalized": "1.28.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", - "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1", - "symfony/polyfill-php80": "^1.14" + "php": ">=7.2" }, - "time": "2023-08-16T06:22:46+00:00", + "time": "2024-09-09T11:45:10+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "installation-source": "dist", @@ -4306,7 +4127,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" }, "funding": [ { @@ -4326,17 +4147,17 @@ }, { "name": "symfony/routing", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.22", + "version_normalized": "6.4.22.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "98eab13a07fddc85766f1756129c69f207ffbc21" + "reference": "1f5234e8457164a3a0038a4c0a4ba27876a9c670" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21", - "reference": "98eab13a07fddc85766f1756129c69f207ffbc21", + "url": "https://api.github.com/repos/symfony/routing/zipball/1f5234e8457164a3a0038a4c0a4ba27876a9c670", + "reference": "1f5234e8457164a3a0038a4c0a4ba27876a9c670", "shasum": "" }, "require": { @@ -4358,7 +4179,7 @@ "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2023-12-29T15:34:34+00:00", + "time": "2025-04-27T16:08:38+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4392,7 +4213,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.2" + "source": "https://github.com/symfony/routing/tree/v6.4.22" }, "funding": [ { @@ -4412,17 +4233,17 @@ }, { "name": "symfony/runtime", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "86539231fadfdc7f7e9911d6fa7ed84a606e7d34" + "reference": "ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/86539231fadfdc7f7e9911d6fa7ed84a606e7d34", - "reference": "86539231fadfdc7f7e9911d6fa7ed84a606e7d34", + "url": "https://api.github.com/repos/symfony/runtime/zipball/ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f", + "reference": "ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f", "shasum": "" }, "require": { @@ -4439,7 +4260,7 @@ "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^5.4|^6.0|^7.0" }, - "time": "2023-10-18T09:43:34+00:00", + "time": "2025-06-13T07:44:14+00:00", "type": "composer-plugin", "extra": { "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" @@ -4474,7 +4295,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v6.4.0" + "source": "https://github.com/symfony/runtime/tree/v6.4.23" }, "funding": [ { @@ -4494,35 +4315,36 @@ }, { "name": "symfony/service-contracts", - "version": "v3.4.1", - "version_normalized": "3.4.1.0", + "version": "v3.6.0", + "version_normalized": "3.6.0.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", - "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^1.1|^2.0" + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "time": "2023-12-26T14:02:43+00:00", + "time": "2025-04-25T09:37:31+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "installation-source": "dist", @@ -4559,7 +4381,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -4579,24 +4401,24 @@ }, { "name": "symfony/stopwatch", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.19", + "version_normalized": "6.4.19.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2" + "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", - "reference": "fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", + "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", "shasum": "" }, "require": { "php": ">=8.1", "symfony/service-contracts": "^2.5|^3" }, - "time": "2023-02-16T10:14:28+00:00", + "time": "2025-02-21T10:06:30+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4624,7 +4446,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.0" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.19" }, "funding": [ { @@ -4644,17 +4466,17 @@ }, { "name": "symfony/string", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.21", + "version_normalized": "6.4.21.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "url": "https://api.github.com/repos/symfony/string/zipball/73e2c6966a5aef1d4892873ed5322245295370c6", + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6", "shasum": "" }, "require": { @@ -4674,7 +4496,7 @@ "symfony/translation-contracts": "^2.5|^3.0", "symfony/var-exporter": "^5.4|^6.0|^7.0" }, - "time": "2023-12-10T16:15:48+00:00", + "time": "2025-04-18T15:23:29+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4713,7 +4535,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.2" + "source": "https://github.com/symfony/string/tree/v6.4.21" }, "funding": [ { @@ -4733,31 +4555,31 @@ }, { "name": "symfony/translation-contracts", - "version": "v3.4.0", - "version_normalized": "3.4.0.0", + "version": "v3.6.0", + "version_normalized": "3.6.0.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5" + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/dee0c6e5b4c07ce851b462530088e64b255ac9c5", - "reference": "dee0c6e5b4c07ce851b462530088e64b255ac9c5", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", "shasum": "" }, "require": { "php": ">=8.1" }, - "time": "2023-07-25T15:08:44+00:00", + "time": "2024-09-27T08:32:26+00:00", "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.4-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "installation-source": "dist", @@ -4794,7 +4616,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.4.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" }, "funding": [ { @@ -4814,17 +4636,17 @@ }, { "name": "symfony/twig-bridge", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.22", + "version_normalized": "6.4.22.0", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf" + "reference": "04ab306a2f2c9dbd46f4363383812954f704af9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf", - "reference": "142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/04ab306a2f2c9dbd46f4363383812954f704af9d", + "reference": "04ab306a2f2c9dbd46f4363383812954f704af9d", "shasum": "" }, "require": { @@ -4855,7 +4677,7 @@ "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/form": "^6.4|^7.0", + "symfony/form": "^6.4.20|^7.2.5", "symfony/html-sanitizer": "^6.1|^7.0", "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -4868,7 +4690,7 @@ "symfony/security-core": "^5.4|^6.0|^7.0", "symfony/security-csrf": "^5.4|^6.0|^7.0", "symfony/security-http": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/serializer": "^6.4.3|^7.0.3", "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/translation": "^6.1|^7.0", "symfony/web-link": "^5.4|^6.0|^7.0", @@ -4878,7 +4700,7 @@ "twig/inky-extra": "^2.12|^3", "twig/markdown-extra": "^2.12|^3" }, - "time": "2023-11-25T08:25:13+00:00", + "time": "2025-05-16T08:23:44+00:00", "type": "symfony-bridge", "installation-source": "dist", "autoload": { @@ -4906,7 +4728,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.0" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.22" }, "funding": [ { @@ -4926,17 +4748,17 @@ }, { "name": "symfony/twig-bundle", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "35d84393e598dfb774e6a2bf49e5229a8a6dbe4c" + "reference": "ef970ed7eb9e547d21628e4c803de0943759cbcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/35d84393e598dfb774e6a2bf49e5229a8a6dbe4c", - "reference": "35d84393e598dfb774e6a2bf49e5229a8a6dbe4c", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/ef970ed7eb9e547d21628e4c803de0943759cbcd", + "reference": "ef970ed7eb9e547d21628e4c803de0943759cbcd", "shasum": "" }, "require": { @@ -4965,7 +4787,7 @@ "symfony/web-link": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2023-11-07T14:57:07+00:00", + "time": "2025-06-20T20:02:07+00:00", "type": "symfony-bundle", "installation-source": "dist", "autoload": { @@ -4993,7 +4815,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.4.0" + "source": "https://github.com/symfony/twig-bundle/tree/v6.4.23" }, "funding": [ { @@ -5013,17 +4835,17 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f" + "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", - "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", + "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", "shasum": "" }, "require": { @@ -5043,7 +4865,7 @@ "symfony/uid": "^5.4|^6.0|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "time": "2023-12-28T19:16:56+00:00", + "time": "2025-06-27T15:05:27+00:00", "bin": [ "Resources/bin/var-dump-server" ], @@ -5081,7 +4903,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.2" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.23" }, "funding": [ { @@ -5101,17 +4923,17 @@ }, { "name": "symfony/var-exporter", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.22", + "version_normalized": "6.4.22.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e" + "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5fe9a0021b8d35e67d914716ec8de50716a68e7e", - "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f28cf841f5654955c9f88ceaf4b9dc29571988a9", + "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9", "shasum": "" }, "require": { @@ -5119,9 +4941,11 @@ "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2023-12-27T08:18:35+00:00", + "time": "2025-05-14T13:00:13+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -5159,7 +4983,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.2" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.22" }, "funding": [ { @@ -5179,17 +5003,17 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.2", - "version_normalized": "6.4.2.0", + "version": "v6.4.19", + "version_normalized": "6.4.19.0", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2" + "reference": "7d1026a8e950d416cb5148ae88ac23db5d264839" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/38462d16856740ec0d1ba2cb902eebf09100dde2", - "reference": "38462d16856740ec0d1ba2cb902eebf09100dde2", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/7d1026a8e950d416cb5148ae88ac23db5d264839", + "reference": "7d1026a8e950d416cb5148ae88ac23db5d264839", "shasum": "" }, "require": { @@ -5213,7 +5037,7 @@ "symfony/css-selector": "^5.4|^6.0|^7.0", "symfony/stopwatch": "^5.4|^6.0|^7.0" }, - "time": "2023-12-27T08:18:35+00:00", + "time": "2025-02-14T12:21:59+00:00", "type": "symfony-bundle", "installation-source": "dist", "autoload": { @@ -5244,7 +5068,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.2" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.19" }, "funding": [ { @@ -5264,17 +5088,17 @@ }, { "name": "symfony/yaml", - "version": "v6.4.0", - "version_normalized": "6.4.0.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587" + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4f9237a1bb42455d609e6687d2613dde5b41a587", - "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587", + "url": "https://api.github.com/repos/symfony/yaml/zipball/93e29e0deb5f1b2e360adfb389a20d25eb81a27b", + "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b", "shasum": "" }, "require": { @@ -5288,7 +5112,7 @@ "require-dev": { "symfony/console": "^5.4|^6.0|^7.0" }, - "time": "2023-11-06T11:00:25+00:00", + "time": "2025-06-03T06:46:12+00:00", "bin": [ "Resources/bin/yaml-lint" ], @@ -5319,7 +5143,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.0" + "source": "https://github.com/symfony/yaml/tree/v6.4.23" }, "funding": [ { diff --git a/lib/composer/installed.php b/lib/composer/installed.php index ae0312d77..207cfc3e3 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' => '3da33c4c647c709b6e3e1e62691f2b8a2df0d482', + 'reference' => '44829e95203e2e45b53a46861ffbd6b663d97d05', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -22,7 +22,7 @@ 'combodo/itop' => array( 'pretty_version' => 'dev-develop', 'version' => 'dev-develop', - 'reference' => '3da33c4c647c709b6e3e1e62691f2b8a2df0d482', + 'reference' => '44829e95203e2e45b53a46861ffbd6b663d97d05', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -360,18 +360,18 @@ 'dev_requirement' => false, ), 'symfony/cache' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '14a75869bbb41cb35bc5d9d322473928c6f3f978', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => 'c88690befb8d4a85dc321fb78d677507f5eb141b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/cache-contracts' => array( - 'pretty_version' => 'v3.4.0', - 'version' => '3.4.0.0', - 'reference' => '1d74b127da04ffa87aa940abe15446fa89653778', + 'pretty_version' => 'v3.6.0', + 'version' => '3.6.0.0', + 'reference' => '5d68a57d66910405e5c0b63d6f0af941e66fc868', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache-contracts', 'aliases' => array(), @@ -384,90 +384,90 @@ ), ), 'symfony/config' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '5d33e0fb707d603330e0edfd4691803a1253572e', + 'pretty_version' => 'v6.4.22', + 'version' => '6.4.22.0', + 'reference' => 'af5917a3b1571f54689e56677a3f06440d2fe4c7', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/config', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/console' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '0254811a143e6bc6c8deea08b589a7e68a37f625', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => '9056771b8eca08d026cd3280deeec3cfd99c4d93', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/css-selector' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'd036c6c0d0b09e24a14a35f8292146a658f986e4', + 'pretty_version' => 'v6.4.13', + 'version' => '6.4.13.0', + 'reference' => 'cb23e97813c5837a041b73a6d63a9ddff0778f5e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/debug-bundle' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '1e07027423d1d37125b60a50997ada26a9d9d202', + 'pretty_version' => 'v6.4.13', + 'version' => '6.4.13.0', + 'reference' => '7bcfaff39e094cc09455201916d016d9b2ae08ff', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/debug-bundle', 'aliases' => array(), 'dev_requirement' => true, ), 'symfony/dependency-injection' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '226ea431b1eda6f0d9f5a4b278757171960bb195', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => '0d9f24f3de0a83573fce5c9ed025d6306c6e166b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/deprecation-contracts' => array( - 'pretty_version' => 'v3.4.0', - 'version' => '3.4.0.0', - 'reference' => '7c3aff79d10325257a001fcf92d991f24fc967cf', + 'pretty_version' => 'v3.6.0', + 'version' => '3.6.0.0', + 'reference' => '63afe740e99a13ba87ec199bb07bbdee937a5b62', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/dotenv' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '835f8d2d1022934ac038519de40b88158798c96f', + 'pretty_version' => 'v6.4.16', + 'version' => '6.4.16.0', + 'reference' => '1ac5e7e7e862d4d574258daf08bd569ba926e4a5', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dotenv', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/error-handler' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'c873490a1c97b3a0a4838afc36ff36c112d02788', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => 'b088e0b175c30b4e06d8085200fa465b586f44fa', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/error-handler', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/event-dispatcher' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => 'e95216850555cd55e71b857eb9d6c2674124603a', + 'pretty_version' => 'v6.4.13', + 'version' => '6.4.13.0', + 'reference' => '0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/event-dispatcher-contracts' => array( - 'pretty_version' => 'v3.4.0', - 'version' => '3.4.0.0', - 'reference' => 'a76aed96a42d2b521153fb382d418e30d18b59df', + 'pretty_version' => 'v3.6.0', + 'version' => '3.6.0.0', + 'reference' => '59eb412e93815df44f05f342958efa9f46b1e586', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', 'aliases' => array(), @@ -480,116 +480,98 @@ ), ), 'symfony/filesystem' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '952a8cb588c3bc6ce76f6023000fb932f16a6e59', + 'pretty_version' => 'v6.4.13', + 'version' => '6.4.13.0', + 'reference' => '4856c9cf585d5a0313d8d35afd681a526f038dd3', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/filesystem', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/finder' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '11d736e97f116ac375a81f96e662911a34cd50ce', + 'pretty_version' => 'v6.4.17', + 'version' => '6.4.17.0', + 'reference' => '1d0e8266248c5d9ab6a87e3789e6dc482af3c9c7', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/framework-bundle' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => 'c26a221e0462027d1f9d4a802ed63f8ab07a43d0', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => 'ff892d3ab4b8aa35921bc2120a4b31d57948fe22', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/framework-bundle', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-foundation' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '172d807f9ef3fc3fbed8377cc57c20d389269271', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => '452d19f945ee41345fd8a50c18b60783546b7bd3', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-kernel' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '13e8387320b5942d0dc408440c888e2d526efef4', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => '2bb2cba685aabd859f22cf6946554e8e7f3c329a', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-kernel', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-ctype' => array( - 'pretty_version' => 'v1.28.0', - 'version' => '1.28.0.0', - 'reference' => 'ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb', + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-grapheme' => array( - 'pretty_version' => 'v1.28.0', - 'version' => '1.28.0.0', - 'reference' => '875e90aeea2777b6f135677f618529449334a612', + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'reference' => 'b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-idn' => array( - 'pretty_version' => 'v1.28.0', - 'version' => '1.28.0.0', - 'reference' => 'ecaafce9f77234a6a449d29e49267ba10499116d', + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'reference' => '9614ac4d8061dc257ecc64cba1b140873dce8ad3', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-normalizer' => array( - 'pretty_version' => 'v1.28.0', - 'version' => '1.28.0.0', - 'reference' => '8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92', + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'reference' => '3833d7255cc303546435cb650316bff708a1c75c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-mbstring' => array( - 'pretty_version' => 'v1.28.0', - 'version' => '1.28.0.0', - 'reference' => '42292d99c55abe617799667f454222c54c60e229', + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'reference' => '6d857f4d76bd4b343eac26d6b539585d2bc56493', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false, ), - 'symfony/polyfill-php72' => array( - 'pretty_version' => 'v1.28.0', - 'version' => '1.28.0.0', - 'reference' => '70f4aebd92afca2f865444d30a4d2151c13c3179', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php72', - 'aliases' => array(), - 'dev_requirement' => false, - ), - 'symfony/polyfill-php80' => array( - 'pretty_version' => 'v1.28.0', - 'version' => '1.28.0.0', - 'reference' => '6caa57379c4aec19c0a12a38b59b26487dcfe4b5', - 'type' => 'library', - 'install_path' => __DIR__ . '/../symfony/polyfill-php80', - 'aliases' => array(), - 'dev_requirement' => false, - ), 'symfony/polyfill-php81' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', 'reference' => '4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php81', @@ -597,36 +579,36 @@ 'dev_requirement' => false, ), 'symfony/polyfill-php83' => array( - 'pretty_version' => 'v1.28.0', - 'version' => '1.28.0.0', - 'reference' => 'b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11', + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', + 'reference' => '2fb86d65e2d424369ad2905e83b236a8805ba491', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php83', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/routing' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '98eab13a07fddc85766f1756129c69f207ffbc21', + 'pretty_version' => 'v6.4.22', + 'version' => '6.4.22.0', + 'reference' => '1f5234e8457164a3a0038a4c0a4ba27876a9c670', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/routing', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/runtime' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '86539231fadfdc7f7e9911d6fa7ed84a606e7d34', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => 'ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f', 'type' => 'composer-plugin', 'install_path' => __DIR__ . '/../symfony/runtime', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/service-contracts' => array( - 'pretty_version' => 'v3.4.1', - 'version' => '3.4.1.0', - 'reference' => 'fe07cbc8d837f60caf7018068e350cc5163681a0', + 'pretty_version' => 'v3.6.0', + 'version' => '3.6.0.0', + 'reference' => 'f021b05a130d35510bd6b25fe9053c2a8a15d5d4', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), @@ -639,81 +621,81 @@ ), ), 'symfony/stopwatch' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => 'fc47f1015ec80927ff64ba9094dfe8b9d48fe9f2', + 'pretty_version' => 'v6.4.19', + 'version' => '6.4.19.0', + 'reference' => 'dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/stopwatch', 'aliases' => array(), 'dev_requirement' => true, ), 'symfony/string' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '7cb80bc10bfcdf6b5492741c0b9357dac66940bc', + 'pretty_version' => 'v6.4.21', + 'version' => '6.4.21.0', + 'reference' => '73e2c6966a5aef1d4892873ed5322245295370c6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/translation-contracts' => array( - 'pretty_version' => 'v3.4.0', - 'version' => '3.4.0.0', - 'reference' => 'dee0c6e5b4c07ce851b462530088e64b255ac9c5', + 'pretty_version' => 'v3.6.0', + 'version' => '3.6.0.0', + 'reference' => 'df210c7a2573f1913b2d17cc95f90f53a73d8f7d', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation-contracts', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/twig-bridge' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '142bc3ad4a61d7eedf7cc21d8ef2bd8a8e7417bf', + 'pretty_version' => 'v6.4.22', + 'version' => '6.4.22.0', + 'reference' => '04ab306a2f2c9dbd46f4363383812954f704af9d', 'type' => 'symfony-bridge', 'install_path' => __DIR__ . '/../symfony/twig-bridge', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/twig-bundle' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '35d84393e598dfb774e6a2bf49e5229a8a6dbe4c', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => 'ef970ed7eb9e547d21628e4c803de0943759cbcd', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/twig-bundle', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/var-dumper' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '68d6573ec98715ddcae5a0a85bee3c1c27a4c33f', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => 'd55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/var-exporter' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '5fe9a0021b8d35e67d914716ec8de50716a68e7e', + 'pretty_version' => 'v6.4.22', + 'version' => '6.4.22.0', + 'reference' => 'f28cf841f5654955c9f88ceaf4b9dc29571988a9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-exporter', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/web-profiler-bundle' => array( - 'pretty_version' => 'v6.4.2', - 'version' => '6.4.2.0', - 'reference' => '38462d16856740ec0d1ba2cb902eebf09100dde2', + 'pretty_version' => 'v6.4.19', + 'version' => '6.4.19.0', + 'reference' => '7d1026a8e950d416cb5148ae88ac23db5d264839', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/web-profiler-bundle', 'aliases' => array(), 'dev_requirement' => true, ), 'symfony/yaml' => array( - 'pretty_version' => 'v6.4.0', - 'version' => '6.4.0.0', - 'reference' => '4f9237a1bb42455d609e6687d2613dde5b41a587', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => '93e29e0deb5f1b2e360adfb389a20d25eb81a27b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/yaml', 'aliases' => array(), diff --git a/lib/composer/platform_check.php b/lib/composer/platform_check.php index dee74e173..72145773d 100644 --- a/lib/composer/platform_check.php +++ b/lib/composer/platform_check.php @@ -36,8 +36,7 @@ if ($issues) { echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; } } - trigger_error( - 'Composer detected issues in your platform: ' . implode(' ', $issues), - E_USER_ERROR + throw new \RuntimeException( + 'Composer detected issues in your platform: ' . implode(' ', $issues) ); } diff --git a/lib/symfony/cache-contracts/CacheInterface.php b/lib/symfony/cache-contracts/CacheInterface.php index a4fcea731..3e4aaf65c 100644 --- a/lib/symfony/cache-contracts/CacheInterface.php +++ b/lib/symfony/cache-contracts/CacheInterface.php @@ -44,7 +44,7 @@ interface CacheInterface * * @throws InvalidArgumentException When $key is not valid or when $beta is negative */ - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed; + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed; /** * Removes an item from the pool. diff --git a/lib/symfony/cache-contracts/CacheTrait.php b/lib/symfony/cache-contracts/CacheTrait.php index 8a4b0bda8..4c5449b9d 100644 --- a/lib/symfony/cache-contracts/CacheTrait.php +++ b/lib/symfony/cache-contracts/CacheTrait.php @@ -25,7 +25,7 @@ class_exists(InvalidArgumentException::class); */ trait CacheTrait { - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed { return $this->doGet($this, $key, $callback, $beta, $metadata); } @@ -35,10 +35,10 @@ trait CacheTrait return $this->deleteItem($key); } - private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null): mixed + private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null, ?LoggerInterface $logger = null): mixed { if (0 > $beta ??= 1.0) { - throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException {}; + throw new class(\sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException {}; } $item = $pool->getItem($key); @@ -54,7 +54,7 @@ trait CacheTrait $item->expiresAt(null); $logger?->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [ 'key' => $key, - 'delta' => sprintf('%.1f', $expiry - $now), + 'delta' => \sprintf('%.1f', $expiry - $now), ]); } } diff --git a/lib/symfony/cache-contracts/NamespacedPoolInterface.php b/lib/symfony/cache-contracts/NamespacedPoolInterface.php new file mode 100644 index 000000000..cd67bc09b --- /dev/null +++ b/lib/symfony/cache-contracts/NamespacedPoolInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\Cache; + +use Psr\Cache\InvalidArgumentException; + +/** + * Enables namespace-based invalidation by prefixing keys with backend-native namespace separators. + * + * Note that calling `withSubNamespace()` MUST NOT mutate the pool, but return a new instance instead. + * + * When tags are used, they MUST ignore sub-namespaces. + * + * @author Nicolas Grekas + */ +interface NamespacedPoolInterface +{ + /** + * @throws InvalidArgumentException If the namespace contains characters found in ItemInterface's RESERVED_CHARACTERS + */ + public function withSubNamespace(string $namespace): static; +} diff --git a/lib/symfony/cache-contracts/composer.json b/lib/symfony/cache-contracts/composer.json index f80d0b559..b713c2901 100644 --- a/lib/symfony/cache-contracts/composer.json +++ b/lib/symfony/cache-contracts/composer.json @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.6-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/lib/symfony/cache/Adapter/AbstractAdapter.php b/lib/symfony/cache/Adapter/AbstractAdapter.php index ed90f4716..7525fe039 100644 --- a/lib/symfony/cache/Adapter/AbstractAdapter.php +++ b/lib/symfony/cache/Adapter/AbstractAdapter.php @@ -86,7 +86,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg * * Using ApcuAdapter makes system caches compatible with read-only filesystems. */ - public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, LoggerInterface $logger = null): AdapterInterface + public static function createSystemCache(string $namespace, int $defaultLifetime, string $version, string $directory, ?LoggerInterface $logger = null): AdapterInterface { $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true); if (null !== $logger) { diff --git a/lib/symfony/cache/Adapter/ApcuAdapter.php b/lib/symfony/cache/Adapter/ApcuAdapter.php index 3dc93fd54..c64a603c4 100644 --- a/lib/symfony/cache/Adapter/ApcuAdapter.php +++ b/lib/symfony/cache/Adapter/ApcuAdapter.php @@ -25,7 +25,7 @@ class ApcuAdapter extends AbstractAdapter /** * @throws CacheException if APCu is not enabled */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null, MarshallerInterface $marshaller = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $version = null, ?MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('APCu is not enabled.'); @@ -101,19 +101,10 @@ class ApcuAdapter extends AbstractAdapter return $failed; } - try { - if (false === $failures = apcu_store($values, null, $lifetime)) { - $failures = $values; - } - - return array_keys($failures); - } catch (\Throwable $e) { - if (1 === \count($values)) { - // Workaround https://github.com/krakjoe/apcu/issues/170 - apcu_delete(array_key_first($values)); - } - - throw $e; + if (false === $failures = apcu_store($values, null, $lifetime)) { + $failures = $values; } + + return array_keys($failures); } } diff --git a/lib/symfony/cache/Adapter/ArrayAdapter.php b/lib/symfony/cache/Adapter/ArrayAdapter.php index 1100c7734..8ebfc4483 100644 --- a/lib/symfony/cache/Adapter/ArrayAdapter.php +++ b/lib/symfony/cache/Adapter/ArrayAdapter.php @@ -74,7 +74,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter ); } - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed { $item = $this->getItem($key); $metadata = $item->getMetadata(); @@ -312,7 +312,9 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter try { $serialized = serialize($value); } catch (\Exception $e) { - unset($this->values[$key], $this->tags[$key]); + if (!isset($this->expiries[$key])) { + unset($this->values[$key]); + } $type = get_debug_type($value); $message = sprintf('Failed to save key "{key}" of type %s: %s', $type, $e->getMessage()); CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e, 'cache-adapter' => get_debug_type($this)]); diff --git a/lib/symfony/cache/Adapter/ChainAdapter.php b/lib/symfony/cache/Adapter/ChainAdapter.php index 8c2e7e111..221b1fb5d 100644 --- a/lib/symfony/cache/Adapter/ChainAdapter.php +++ b/lib/symfony/cache/Adapter/ChainAdapter.php @@ -88,7 +88,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa ); } - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed { $doSave = true; $callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) { @@ -98,7 +98,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa return $value; }; - $wrap = function (CacheItem $item = null, bool &$save = true) use ($key, $callback, $beta, &$wrap, &$doSave, &$metadata) { + $wrap = function (?CacheItem $item = null, bool &$save = true) use ($key, $callback, $beta, &$wrap, &$doSave, &$metadata) { static $lastItem; static $i = 0; $adapter = $this->adapters[$i]; diff --git a/lib/symfony/cache/Adapter/CouchbaseBucketAdapter.php b/lib/symfony/cache/Adapter/CouchbaseBucketAdapter.php index f8cb92dbf..18136da17 100644 --- a/lib/symfony/cache/Adapter/CouchbaseBucketAdapter.php +++ b/lib/symfony/cache/Adapter/CouchbaseBucketAdapter.php @@ -39,7 +39,7 @@ class CouchbaseBucketAdapter extends AbstractAdapter private \CouchbaseBucket $bucket; private MarshallerInterface $marshaller; - public function __construct(\CouchbaseBucket $bucket, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) + public function __construct(\CouchbaseBucket $bucket, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('Couchbase >= 2.6.0 < 3.0.0 is required.'); diff --git a/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php b/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php index b5bb603e3..a1cfb0843 100644 --- a/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php +++ b/lib/symfony/cache/Adapter/CouchbaseCollectionAdapter.php @@ -32,7 +32,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter private Collection $connection; private MarshallerInterface $marshaller; - public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) + public function __construct(Collection $connection, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('Couchbase >= 3.0.5 < 4.0.0 is required.'); @@ -183,7 +183,7 @@ class CouchbaseCollectionAdapter extends AbstractAdapter } $upsertOptions = new UpsertOptions(); - $upsertOptions->expiry(\DateTimeImmutable::createFromFormat('U', time() + $lifetime)); + $upsertOptions->expiry($lifetime); $ko = []; foreach ($values as $key => $value) { diff --git a/lib/symfony/cache/Adapter/DoctrineDbalAdapter.php b/lib/symfony/cache/Adapter/DoctrineDbalAdapter.php index a92e6d420..9d02be3aa 100644 --- a/lib/symfony/cache/Adapter/DoctrineDbalAdapter.php +++ b/lib/symfony/cache/Adapter/DoctrineDbalAdapter.php @@ -59,7 +59,7 @@ class DoctrineDbalAdapter extends AbstractAdapter implements PruneableInterface * * @throws InvalidArgumentException When namespace contains invalid characters */ - public function __construct(Connection|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) + public function __construct(Connection|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], ?MarshallerInterface $marshaller = null) { if (isset($namespace[0]) && preg_match('#[^-+.A-Za-z0-9]#', $namespace, $match)) { throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+.A-Za-z0-9] are allowed.', $match[0])); diff --git a/lib/symfony/cache/Adapter/FilesystemAdapter.php b/lib/symfony/cache/Adapter/FilesystemAdapter.php index 7185dd487..13daa568c 100644 --- a/lib/symfony/cache/Adapter/FilesystemAdapter.php +++ b/lib/symfony/cache/Adapter/FilesystemAdapter.php @@ -20,7 +20,7 @@ class FilesystemAdapter extends AbstractAdapter implements PruneableInterface { use FilesystemTrait; - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, ?MarshallerInterface $marshaller = null) { $this->marshaller = $marshaller ?? new DefaultMarshaller(); parent::__construct('', $defaultLifetime); diff --git a/lib/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/lib/symfony/cache/Adapter/FilesystemTagAwareAdapter.php index e78536794..80edee433 100644 --- a/lib/symfony/cache/Adapter/FilesystemTagAwareAdapter.php +++ b/lib/symfony/cache/Adapter/FilesystemTagAwareAdapter.php @@ -35,7 +35,7 @@ class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements Prune */ private const TAG_FOLDER = 'tags'; - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null) + public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, ?MarshallerInterface $marshaller = null) { $this->marshaller = new TagAwareMarshaller($marshaller); parent::__construct('', $defaultLifetime); diff --git a/lib/symfony/cache/Adapter/MemcachedAdapter.php b/lib/symfony/cache/Adapter/MemcachedAdapter.php index 23fc94d45..0efa152ee 100644 --- a/lib/symfony/cache/Adapter/MemcachedAdapter.php +++ b/lib/symfony/cache/Adapter/MemcachedAdapter.php @@ -45,7 +45,7 @@ class MemcachedAdapter extends AbstractAdapter * * Using a MemcachedAdapter as a pure items store is fine. */ - public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) + public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) { if (!static::isSupported()) { throw new CacheException('Memcached > 3.1.5 is required.'); @@ -114,6 +114,8 @@ class MemcachedAdapter extends AbstractAdapter $params = preg_replace_callback('#^memcached:(//)?(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { if (!empty($m[2])) { [$username, $password] = explode(':', $m[2], 2) + [1 => null]; + $username = rawurldecode($username); + $password = null !== $password ? rawurldecode($password) : null; } return 'file:'.($m[1] ?? ''); diff --git a/lib/symfony/cache/Adapter/NullAdapter.php b/lib/symfony/cache/Adapter/NullAdapter.php index 07c7af816..d5d2ef6b4 100644 --- a/lib/symfony/cache/Adapter/NullAdapter.php +++ b/lib/symfony/cache/Adapter/NullAdapter.php @@ -37,7 +37,7 @@ class NullAdapter implements AdapterInterface, CacheInterface ); } - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed { $save = true; diff --git a/lib/symfony/cache/Adapter/PdoAdapter.php b/lib/symfony/cache/Adapter/PdoAdapter.php index 815c622b0..c79b73959 100644 --- a/lib/symfony/cache/Adapter/PdoAdapter.php +++ b/lib/symfony/cache/Adapter/PdoAdapter.php @@ -54,7 +54,7 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface * @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION * @throws InvalidArgumentException When namespace contains invalid characters */ - public function __construct(#[\SensitiveParameter] \PDO|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null) + public function __construct(#[\SensitiveParameter] \PDO|string $connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], ?MarshallerInterface $marshaller = null) { if (\is_string($connOrDsn) && str_contains($connOrDsn, '://')) { throw new InvalidArgumentException(sprintf('Usage of Doctrine DBAL URL with "%s" is not supported. Use a PDO DSN or "%s" instead.', __CLASS__, DoctrineDbalAdapter::class)); @@ -374,10 +374,10 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface private function isTableMissing(\PDOException $exception): bool { $driver = $this->getDriver(); - $code = $exception->getCode(); + [$sqlState, $code] = $exception->errorInfo ?? [null, $exception->getCode()]; return match ($driver) { - 'pgsql' => '42P01' === $code, + 'pgsql' => '42P01' === $sqlState, 'sqlite' => str_contains($exception->getMessage(), 'no such table:'), 'oci' => 942 === $code, 'sqlsrv' => 208 === $code, diff --git a/lib/symfony/cache/Adapter/PhpArrayAdapter.php b/lib/symfony/cache/Adapter/PhpArrayAdapter.php index f6decd848..0cda1cce8 100644 --- a/lib/symfony/cache/Adapter/PhpArrayAdapter.php +++ b/lib/symfony/cache/Adapter/PhpArrayAdapter.php @@ -78,7 +78,7 @@ class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInte return new static($file, $fallbackPool); } - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed { if (!isset($this->values)) { $this->initialize(); diff --git a/lib/symfony/cache/Adapter/PhpFilesAdapter.php b/lib/symfony/cache/Adapter/PhpFilesAdapter.php index 41ea8604c..e550276df 100644 --- a/lib/symfony/cache/Adapter/PhpFilesAdapter.php +++ b/lib/symfony/cache/Adapter/PhpFilesAdapter.php @@ -43,7 +43,7 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface * * @throws CacheException if OPcache is not enabled */ - public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false) + public function __construct(string $namespace = '', int $defaultLifetime = 0, ?string $directory = null, bool $appendOnly = false) { $this->appendOnly = $appendOnly; self::$startTime ??= $_SERVER['REQUEST_TIME'] ?? time(); diff --git a/lib/symfony/cache/Adapter/ProxyAdapter.php b/lib/symfony/cache/Adapter/ProxyAdapter.php index 88fccde4a..c022dd5fa 100644 --- a/lib/symfony/cache/Adapter/ProxyAdapter.php +++ b/lib/symfony/cache/Adapter/ProxyAdapter.php @@ -80,7 +80,7 @@ class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterfa ); } - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed { if (!$this->pool instanceof CacheInterface) { return $this->doGet($this, $key, $callback, $beta, $metadata); diff --git a/lib/symfony/cache/Adapter/RedisAdapter.php b/lib/symfony/cache/Adapter/RedisAdapter.php index d8e37b1d7..e33f2f65f 100644 --- a/lib/symfony/cache/Adapter/RedisAdapter.php +++ b/lib/symfony/cache/Adapter/RedisAdapter.php @@ -18,7 +18,7 @@ class RedisAdapter extends AbstractAdapter { use RedisTrait; - public function __construct(\Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|\Relay\Relay $redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) + public function __construct(\Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|\Relay\Relay $redis, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) { $this->init($redis, $namespace, $defaultLifetime, $marshaller); } diff --git a/lib/symfony/cache/Adapter/RedisTagAwareAdapter.php b/lib/symfony/cache/Adapter/RedisTagAwareAdapter.php index a3ef9f109..a44ef986d 100644 --- a/lib/symfony/cache/Adapter/RedisTagAwareAdapter.php +++ b/lib/symfony/cache/Adapter/RedisTagAwareAdapter.php @@ -60,7 +60,7 @@ class RedisTagAwareAdapter extends AbstractTagAwareAdapter private string $redisEvictionPolicy; private string $namespace; - public function __construct(\Redis|Relay|\RedisArray|\RedisCluster|\Predis\ClientInterface $redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null) + public function __construct(\Redis|Relay|\RedisArray|\RedisCluster|\Predis\ClientInterface $redis, string $namespace = '', int $defaultLifetime = 0, ?MarshallerInterface $marshaller = null) { if ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof ClusterInterface && !$redis->getConnection() instanceof PredisCluster) { throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, get_debug_type($redis->getConnection()))); diff --git a/lib/symfony/cache/Adapter/TagAwareAdapter.php b/lib/symfony/cache/Adapter/TagAwareAdapter.php index 187539acc..539ef1697 100644 --- a/lib/symfony/cache/Adapter/TagAwareAdapter.php +++ b/lib/symfony/cache/Adapter/TagAwareAdapter.php @@ -51,7 +51,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac private static \Closure $getTagsByKey; private static \Closure $saveTags; - public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15) + public function __construct(AdapterInterface $itemsPool, ?AdapterInterface $tagsPool = null, float $knownTagVersionsTtl = 0.15) { $this->pool = $itemsPool; $this->tags = $tagsPool ?? $itemsPool; @@ -146,8 +146,6 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac foreach ($keys as $key) { if ('' !== $key && \is_string($key)) { $commit = $commit || isset($this->deferred[$key]); - $key = static::TAGS_PREFIX.$key; - $tagKeys[$key] = $key; // BC with pools populated before v6.1 } } @@ -156,7 +154,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac } try { - $items = $this->pool->getItems($tagKeys + $keys); + $items = $this->pool->getItems($keys); } catch (InvalidArgumentException $e) { $this->pool->getItems($keys); // Should throw an exception @@ -166,18 +164,24 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac $bufferedItems = $itemTags = []; foreach ($items as $key => $item) { - if (isset($tagKeys[$key])) { // BC with pools populated before v6.1 - if ($item->isHit()) { - $itemTags[substr($key, \strlen(static::TAGS_PREFIX))] = $item->get() ?: []; - } - continue; - } - if (null !== $tags = $item->getMetadata()[CacheItem::METADATA_TAGS] ?? null) { $itemTags[$key] = $tags; } $bufferedItems[$key] = $item; + + if (null === $tags) { + $key = "\0tags\0".$key; + $tagKeys[$key] = $key; // BC with pools populated before v6.1 + } + } + + if ($tagKeys) { + foreach ($this->pool->getItems($tagKeys) as $key => $item) { + if ($item->isHit()) { + $itemTags[substr($key, \strlen("\0tags\0"))] = $item->get() ?: []; + } + } } $tagVersions = $this->getTagVersions($itemTags, false); @@ -222,7 +226,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterfac { foreach ($keys as $key) { if ('' !== $key && \is_string($key)) { - $keys[] = static::TAGS_PREFIX.$key; // BC with pools populated before v6.1 + $keys[] = "\0tags\0".$key; // BC with pools populated before v6.1 } } diff --git a/lib/symfony/cache/Adapter/TraceableAdapter.php b/lib/symfony/cache/Adapter/TraceableAdapter.php index 118b00909..8569fa283 100644 --- a/lib/symfony/cache/Adapter/TraceableAdapter.php +++ b/lib/symfony/cache/Adapter/TraceableAdapter.php @@ -35,7 +35,7 @@ class TraceableAdapter implements AdapterInterface, CacheInterface, PruneableInt $this->pool = $pool; } - public function get(string $key, callable $callback, float $beta = null, array &$metadata = null): mixed + public function get(string $key, callable $callback, ?float $beta = null, ?array &$metadata = null): mixed { if (!$this->pool instanceof CacheInterface) { throw new \BadMethodCallException(sprintf('Cannot call "%s::get()": this class doesn\'t implement "%s".', get_debug_type($this->pool), CacheInterface::class)); diff --git a/lib/symfony/cache/CacheItem.php b/lib/symfony/cache/CacheItem.php index 1a81706da..20af82b7b 100644 --- a/lib/symfony/cache/CacheItem.php +++ b/lib/symfony/cache/CacheItem.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache; +use Psr\Cache\CacheItemInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Exception\LogicException; @@ -30,7 +31,7 @@ final class CacheItem implements ItemInterface protected float|int|null $expiry = null; protected array $metadata = []; protected array $newMetadata = []; - protected ?ItemInterface $innerItem = null; + protected ?CacheItemInterface $innerItem = null; protected ?string $poolHash = null; protected bool $isTaggable = false; diff --git a/lib/symfony/cache/DataCollector/CacheDataCollector.php b/lib/symfony/cache/DataCollector/CacheDataCollector.php index 08ab8816c..22a5a0391 100644 --- a/lib/symfony/cache/DataCollector/CacheDataCollector.php +++ b/lib/symfony/cache/DataCollector/CacheDataCollector.php @@ -36,17 +36,9 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter $this->instances[$name] = $instance; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { - $empty = ['calls' => [], 'adapters' => [], 'config' => [], 'options' => [], 'statistics' => []]; - $this->data = ['instances' => $empty, 'total' => $empty]; - foreach ($this->instances as $name => $instance) { - $this->data['instances']['calls'][$name] = $instance->getCalls(); - $this->data['instances']['adapters'][$name] = get_debug_type($instance->getPool()); - } - - $this->data['instances']['statistics'] = $this->calculateStatistics(); - $this->data['total']['statistics'] = $this->calculateTotalStatistics(); + $this->lateCollect(); } public function reset(): void @@ -59,6 +51,15 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter public function lateCollect(): void { + $empty = ['calls' => [], 'adapters' => [], 'config' => [], 'options' => [], 'statistics' => []]; + $this->data = ['instances' => $empty, 'total' => $empty]; + foreach ($this->instances as $name => $instance) { + $this->data['instances']['calls'][$name] = $instance->getCalls(); + $this->data['instances']['adapters'][$name] = get_debug_type($instance->getPool()); + } + + $this->data['instances']['statistics'] = $this->calculateStatistics(); + $this->data['total']['statistics'] = $this->calculateTotalStatistics(); $this->data['instances']['calls'] = $this->cloneVar($this->data['instances']['calls']); } diff --git a/lib/symfony/cache/DependencyInjection/CachePoolPass.php b/lib/symfony/cache/DependencyInjection/CachePoolPass.php index 9c280abbe..80b8a94c9 100644 --- a/lib/symfony/cache/DependencyInjection/CachePoolPass.php +++ b/lib/symfony/cache/DependencyInjection/CachePoolPass.php @@ -58,9 +58,11 @@ class CachePoolPass implements CompilerPassInterface continue; } $class = $adapter->getClass(); + $providers = $adapter->getArguments(); while ($adapter instanceof ChildDefinition) { $adapter = $container->findDefinition($adapter->getParent()); $class = $class ?: $adapter->getClass(); + $providers += $adapter->getArguments(); if ($t = $adapter->getTag('cache.pool')) { $tags[0] += $t[0]; } @@ -90,7 +92,7 @@ class CachePoolPass implements CompilerPassInterface if (ChainAdapter::class === $class) { $adapters = []; - foreach ($adapter->getArgument(0) as $provider => $adapter) { + foreach ($providers['index_0'] ?? $providers[0] as $provider => $adapter) { if ($adapter instanceof ChildDefinition) { $chainedPool = $adapter; } else { @@ -181,11 +183,11 @@ class CachePoolPass implements CompilerPassInterface $container->removeDefinition('cache.early_expiration_handler'); } - $notAliasedCacheClearerId = $aliasedCacheClearerId = 'cache.global_clearer'; - while ($container->hasAlias('cache.global_clearer')) { - $aliasedCacheClearerId = (string) $container->getAlias('cache.global_clearer'); + $notAliasedCacheClearerId = 'cache.global_clearer'; + while ($container->hasAlias($notAliasedCacheClearerId)) { + $notAliasedCacheClearerId = (string) $container->getAlias($notAliasedCacheClearerId); } - if ($container->hasDefinition($aliasedCacheClearerId)) { + if ($container->hasDefinition($notAliasedCacheClearerId)) { $clearers[$notAliasedCacheClearerId] = $allPools; } @@ -197,10 +199,6 @@ class CachePoolPass implements CompilerPassInterface $clearer->setArgument(0, $pools); } $clearer->addTag('cache.pool.clearer'); - - if ('cache.system_clearer' === $id) { - $clearer->addTag('kernel.cache_clearer'); - } } $allPoolsKeys = array_keys($allPools); diff --git a/lib/symfony/cache/LockRegistry.php b/lib/symfony/cache/LockRegistry.php index 4b750cb44..c5c5fde89 100644 --- a/lib/symfony/cache/LockRegistry.php +++ b/lib/symfony/cache/LockRegistry.php @@ -83,7 +83,7 @@ final class LockRegistry return $previousFiles; } - public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null, LoggerInterface $logger = null): mixed + public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, ?\Closure $setMetadata = null, ?LoggerInterface $logger = null): mixed { if ('\\' === \DIRECTORY_SEPARATOR && null === self::$lockedFiles) { // disable locking on Windows by default diff --git a/lib/symfony/cache/Marshaller/DefaultMarshaller.php b/lib/symfony/cache/Marshaller/DefaultMarshaller.php index 973b137ae..34bbeb893 100644 --- a/lib/symfony/cache/Marshaller/DefaultMarshaller.php +++ b/lib/symfony/cache/Marshaller/DefaultMarshaller.php @@ -23,7 +23,7 @@ class DefaultMarshaller implements MarshallerInterface private bool $useIgbinarySerialize = true; private bool $throwOnSerializationFailure = false; - public function __construct(bool $useIgbinarySerialize = null, bool $throwOnSerializationFailure = false) + public function __construct(?bool $useIgbinarySerialize = null, bool $throwOnSerializationFailure = false) { if (null === $useIgbinarySerialize) { $useIgbinarySerialize = \extension_loaded('igbinary') && version_compare('3.1.6', phpversion('igbinary'), '<='); diff --git a/lib/symfony/cache/Marshaller/SodiumMarshaller.php b/lib/symfony/cache/Marshaller/SodiumMarshaller.php index ee64c949a..49eb716a6 100644 --- a/lib/symfony/cache/Marshaller/SodiumMarshaller.php +++ b/lib/symfony/cache/Marshaller/SodiumMarshaller.php @@ -29,7 +29,7 @@ class SodiumMarshaller implements MarshallerInterface * more rotating keys can be provided to decrypt values; * each key must be generated using sodium_crypto_box_keypair() */ - public function __construct(array $decryptionKeys, MarshallerInterface $marshaller = null) + public function __construct(array $decryptionKeys, ?MarshallerInterface $marshaller = null) { if (!self::isSupported()) { throw new CacheException('The "sodium" PHP extension is not loaded.'); diff --git a/lib/symfony/cache/Marshaller/TagAwareMarshaller.php b/lib/symfony/cache/Marshaller/TagAwareMarshaller.php index f5c2867af..825f32cc0 100644 --- a/lib/symfony/cache/Marshaller/TagAwareMarshaller.php +++ b/lib/symfony/cache/Marshaller/TagAwareMarshaller.php @@ -20,7 +20,7 @@ class TagAwareMarshaller implements MarshallerInterface { private MarshallerInterface $marshaller; - public function __construct(MarshallerInterface $marshaller = null) + public function __construct(?MarshallerInterface $marshaller = null) { $this->marshaller = $marshaller ?? new DefaultMarshaller(); } diff --git a/lib/symfony/cache/Messenger/EarlyExpirationDispatcher.php b/lib/symfony/cache/Messenger/EarlyExpirationDispatcher.php index db2dd97d8..8fe0f2515 100644 --- a/lib/symfony/cache/Messenger/EarlyExpirationDispatcher.php +++ b/lib/symfony/cache/Messenger/EarlyExpirationDispatcher.php @@ -27,7 +27,7 @@ class EarlyExpirationDispatcher private ReverseContainer $reverseContainer; private ?\Closure $callbackWrapper; - public function __construct(MessageBusInterface $bus, ReverseContainer $reverseContainer, callable $callbackWrapper = null) + public function __construct(MessageBusInterface $bus, ReverseContainer $reverseContainer, ?callable $callbackWrapper = null) { $this->bus = $bus; $this->reverseContainer = $reverseContainer; @@ -37,7 +37,7 @@ class EarlyExpirationDispatcher /** * @return mixed */ - public function __invoke(callable $callback, CacheItem $item, bool &$save, AdapterInterface $pool, \Closure $setMetadata, LoggerInterface $logger = null) + public function __invoke(callable $callback, CacheItem $item, bool &$save, AdapterInterface $pool, \Closure $setMetadata, ?LoggerInterface $logger = null) { if (!$item->isHit() || null === $message = EarlyExpirationMessage::create($this->reverseContainer, $callback, $item, $pool)) { // The item is stale or the callback cannot be reversed: we must compute the value now diff --git a/lib/symfony/cache/Traits/ContractsTrait.php b/lib/symfony/cache/Traits/ContractsTrait.php index 083ce1f9d..8d830f0ab 100644 --- a/lib/symfony/cache/Traits/ContractsTrait.php +++ b/lib/symfony/cache/Traits/ContractsTrait.php @@ -59,7 +59,7 @@ trait ContractsTrait return $previousWrapper; } - private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null): mixed + private function doGet(AdapterInterface $pool, string $key, callable $callback, ?float $beta, ?array &$metadata = null): mixed { if (0 > $beta ??= 1.0) { throw new InvalidArgumentException(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)); diff --git a/lib/symfony/cache/Traits/FilesystemCommonTrait.php b/lib/symfony/cache/Traits/FilesystemCommonTrait.php index 8772c30d5..3b976b66f 100644 --- a/lib/symfony/cache/Traits/FilesystemCommonTrait.php +++ b/lib/symfony/cache/Traits/FilesystemCommonTrait.php @@ -85,7 +85,7 @@ trait FilesystemCommonTrait return @unlink($file); } - private function write(string $file, string $data, int $expiresAt = null): bool + private function write(string $file, string $data, ?int $expiresAt = null): bool { $unlink = false; set_error_handler(static fn ($type, $message, $file, $line) => throw new \ErrorException($message, 0, $type, $file, $line)); @@ -109,8 +109,13 @@ trait FilesystemCommonTrait touch($tmp, $expiresAt ?: time() + 31556952); // 1 year in seconds } - $success = rename($tmp, $file); - $unlink = !$success; + if ('\\' === \DIRECTORY_SEPARATOR) { + $success = copy($tmp, $file); + $unlink = true; + } else { + $success = rename($tmp, $file); + $unlink = !$success; + } return $success; } finally { @@ -122,7 +127,7 @@ trait FilesystemCommonTrait } } - private function getFile(string $id, bool $mkdir = false, string $directory = null): string + private function getFile(string $id, bool $mkdir = false, ?string $directory = null): string { // Use xxh128 to favor speed over security, which is not an issue here $hash = str_replace('/', '-', base64_encode(hash('xxh128', static::class.$id, true))); diff --git a/lib/symfony/cache/Traits/Redis5Proxy.php b/lib/symfony/cache/Traits/Redis5Proxy.php index 06130cc33..0b2794ee1 100644 --- a/lib/symfony/cache/Traits/Redis5Proxy.php +++ b/lib/symfony/cache/Traits/Redis5Proxy.php @@ -81,7 +81,7 @@ class Redis5Proxy extends \Redis implements ResetInterface, LazyObjectInterface return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->append(...\func_get_args()); } - public function auth($auth) + public function auth(#[\SensitiveParameter] $auth) { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->auth(...\func_get_args()); } diff --git a/lib/symfony/cache/Traits/Redis6Proxy.php b/lib/symfony/cache/Traits/Redis6Proxy.php index 0680404fc..c841d4269 100644 --- a/lib/symfony/cache/Traits/Redis6Proxy.php +++ b/lib/symfony/cache/Traits/Redis6Proxy.php @@ -25,6 +25,7 @@ class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); */ class Redis6Proxy extends \Redis implements ResetInterface, LazyObjectInterface { + use Redis6ProxyTrait; use LazyProxyTrait { resetLazyObject as reset; } @@ -226,11 +227,6 @@ class Redis6Proxy extends \Redis implements ResetInterface, LazyObjectInterface return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->discard(...\func_get_args()); } - public function dump($key): \Redis|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); - } - public function echo($str): \Redis|false|string { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->echo(...\func_get_args()); @@ -511,16 +507,6 @@ class Redis6Proxy extends \Redis implements ResetInterface, LazyObjectInterface return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hMset(...\func_get_args()); } - public function hRandField($key, $options = null): \Redis|array|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hRandField(...\func_get_args()); - } - - public function hSet($key, $member, $value): \Redis|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSet(...\func_get_args()); - } - public function hSetNx($key, $field, $value): \Redis|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSetNx(...\func_get_args()); @@ -651,11 +637,6 @@ class Redis6Proxy extends \Redis implements ResetInterface, LazyObjectInterface return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->ltrim(...\func_get_args()); } - public function mget($keys): \Redis|array - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args()); - } - public function migrate($host, $port, $key, $dstdb, $timeout, $copy = false, $replace = false, #[\SensitiveParameter] $credentials = null): \Redis|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->migrate(...\func_get_args()); @@ -866,11 +847,6 @@ class Redis6Proxy extends \Redis implements ResetInterface, LazyObjectInterface return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sPop(...\func_get_args()); } - public function sRandMember($key, $count = 0): \Redis|array|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sRandMember(...\func_get_args()); - } - public function sUnion($key, ...$other_keys): \Redis|array|false { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sUnion(...\func_get_args()); diff --git a/lib/symfony/cache/Traits/Redis6ProxyTrait.php b/lib/symfony/cache/Traits/Redis6ProxyTrait.php new file mode 100644 index 000000000..34f60cb10 --- /dev/null +++ b/lib/symfony/cache/Traits/Redis6ProxyTrait.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +if (version_compare(phpversion('redis'), '6.1.0-dev', '>=')) { + /** + * @internal + */ + trait Redis6ProxyTrait + { + public function dump($key): \Redis|string|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); + } + + public function hRandField($key, $options = null): \Redis|array|string|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hRandField(...\func_get_args()); + } + + public function hSet($key, ...$fields_and_vals): \Redis|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSet(...\func_get_args()); + } + + public function mget($keys): \Redis|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args()); + } + + public function sRandMember($key, $count = 0): mixed + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sRandMember(...\func_get_args()); + } + + public function waitaof($numlocal, $numreplicas, $timeout): \Redis|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->waitaof(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait Redis6ProxyTrait + { + public function dump($key): \Redis|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); + } + + public function hRandField($key, $options = null): \Redis|array|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hRandField(...\func_get_args()); + } + + public function hSet($key, $member, $value): \Redis|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hSet(...\func_get_args()); + } + + public function mget($keys): \Redis|array + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->mget(...\func_get_args()); + } + + public function sRandMember($key, $count = 0): \Redis|array|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->sRandMember(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/RedisCluster5Proxy.php b/lib/symfony/cache/Traits/RedisCluster5Proxy.php index da23e0f88..511c53dd7 100644 --- a/lib/symfony/cache/Traits/RedisCluster5Proxy.php +++ b/lib/symfony/cache/Traits/RedisCluster5Proxy.php @@ -31,7 +31,7 @@ class RedisCluster5Proxy extends \RedisCluster implements ResetInterface, LazyOb private const LAZY_OBJECT_PROPERTY_SCOPES = []; - public function __construct($name, $seeds = null, $timeout = null, $read_timeout = null, $persistent = null, $auth = null) + public function __construct($name, $seeds = null, $timeout = null, $read_timeout = null, $persistent = null, #[\SensitiveParameter] $auth = null) { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->__construct(...\func_get_args()); } diff --git a/lib/symfony/cache/Traits/RedisCluster6Proxy.php b/lib/symfony/cache/Traits/RedisCluster6Proxy.php index fafc4acf2..c19aa1620 100644 --- a/lib/symfony/cache/Traits/RedisCluster6Proxy.php +++ b/lib/symfony/cache/Traits/RedisCluster6Proxy.php @@ -25,6 +25,7 @@ class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); */ class RedisCluster6Proxy extends \RedisCluster implements ResetInterface, LazyObjectInterface { + use RedisCluster6ProxyTrait; use LazyProxyTrait { resetLazyObject as reset; } @@ -656,11 +657,6 @@ class RedisCluster6Proxy extends \RedisCluster implements ResetInterface, LazyOb return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pttl(...\func_get_args()); } - public function publish($channel, $message): \RedisCluster|bool - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args()); - } - public function pubsub($key_or_address, ...$values): mixed { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pubsub(...\func_get_args()); diff --git a/lib/symfony/cache/Traits/RedisCluster6ProxyTrait.php b/lib/symfony/cache/Traits/RedisCluster6ProxyTrait.php new file mode 100644 index 000000000..9c3169e32 --- /dev/null +++ b/lib/symfony/cache/Traits/RedisCluster6ProxyTrait.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +if (version_compare(phpversion('redis'), '6.1.0-dev', '>')) { + /** + * @internal + */ + trait RedisCluster6ProxyTrait + { + public function getex($key, $options = []): \RedisCluster|string|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getex(...\func_get_args()); + } + + public function publish($channel, $message): \RedisCluster|bool|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args()); + } + + public function waitaof($key_or_address, $numlocal, $numreplicas, $timeout): \RedisCluster|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->waitaof(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait RedisCluster6ProxyTrait + { + public function publish($channel, $message): \RedisCluster|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->publish(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/RedisTrait.php b/lib/symfony/cache/Traits/RedisTrait.php index 4928db07f..2ebaed16f 100644 --- a/lib/symfony/cache/Traits/RedisTrait.php +++ b/lib/symfony/cache/Traits/RedisTrait.php @@ -17,6 +17,7 @@ use Predis\Connection\Aggregate\RedisCluster; use Predis\Connection\Aggregate\ReplicationInterface; use Predis\Connection\Cluster\ClusterInterface as Predis2ClusterInterface; use Predis\Connection\Cluster\RedisCluster as Predis2RedisCluster; +use Predis\Connection\Replication\ReplicationInterface as Predis2ReplicationInterface; use Predis\Response\ErrorInterface; use Predis\Response\Status; use Relay\Relay; @@ -149,10 +150,10 @@ trait RedisTrait if (isset($params['host']) || isset($params['path'])) { if (!isset($params['dbindex']) && isset($params['path'])) { if (preg_match('#/(\d+)?$#', $params['path'], $m)) { - $params['dbindex'] = $m[1] ?? '0'; + $params['dbindex'] = $m[1] ?? $query['dbindex'] ?? '0'; $params['path'] = substr($params['path'], 0, -\strlen($m[0])); } elseif (isset($params['host'])) { - throw new InvalidArgumentException('Invalid Redis DSN: query parameter "dbindex" must be a number.'); + throw new InvalidArgumentException('Invalid Redis DSN: parameter "dbindex" must be a number.'); } } @@ -167,6 +168,10 @@ trait RedisTrait throw new InvalidArgumentException('Invalid Redis DSN: missing host.'); } + if (isset($params['dbindex'], $query['dbindex']) && $params['dbindex'] !== $query['dbindex']) { + throw new InvalidArgumentException('Invalid Redis DSN: path and query "dbindex" parameters mismatch.'); + } + $params += $query + $options + self::$defaultConnectionOptions; if (isset($params['redis_sentinel']) && !class_exists(\Predis\Client::class) && !class_exists(\RedisSentinel::class) && !class_exists(Sentinel::class)) { @@ -228,10 +233,10 @@ trait RedisTrait $options = [ 'host' => $host, 'port' => $port, - 'connectTimeout' => $params['timeout'], + 'connectTimeout' => (float) $params['timeout'], 'persistent' => $params['persistent_id'], - 'retryInterval' => $params['retry_interval'], - 'readTimeout' => $params['read_timeout'], + 'retryInterval' => (int) $params['retry_interval'], + 'readTimeout' => (float) $params['read_timeout'], ]; if ($passAuth) { @@ -242,10 +247,10 @@ trait RedisTrait } else { $extra = $passAuth ? [$params['auth']] : []; - $sentinel = new $sentinelClass($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra); + $sentinel = @new $sentinelClass($host, $port, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval'], $params['read_timeout'], ...$extra); } - if ($address = $sentinel->getMasterAddrByName($params['redis_sentinel'])) { + if ($address = @$sentinel->getMasterAddrByName($params['redis_sentinel'])) { [$host, $port] = $address; } } catch (\RedisException|\Relay\Exception $redisException) { @@ -260,6 +265,22 @@ trait RedisTrait $extra = [ 'stream' => $params['ssl'] ?? null, ]; + $booleanStreamOptions = [ + 'allow_self_signed', + 'capture_peer_cert', + 'capture_peer_cert_chain', + 'disable_compression', + 'SNI_enabled', + 'verify_peer', + 'verify_peer_name', + ]; + + foreach ($extra['stream'] ?? [] as $streamOption => $value) { + if (\in_array($streamOption, $booleanStreamOptions, true) && \is_string($value)) { + $extra['stream'][$streamOption] = filter_var($value, \FILTER_VALIDATE_BOOL); + } + } + if (isset($params['auth'])) { $extra['auth'] = $params['auth']; } @@ -277,7 +298,10 @@ trait RedisTrait } if ((null !== $auth && !$redis->auth($auth)) - || ($params['dbindex'] && !$redis->select($params['dbindex'])) + // Due to a bug in phpredis we must always select the dbindex if persistent pooling is enabled + // @see https://github.com/phpredis/phpredis/issues/1920 + // @see https://github.com/symfony/symfony/issues/51578 + || (($params['dbindex'] || ('pconnect' === $connect && '0' !== \ini_get('redis.pconnect.pooling_enabled'))) && !$redis->select($params['dbindex'])) ) { $e = preg_replace('/^ERR /', '', $redis->getLastError()); throw new InvalidArgumentException('Redis connection failed: '.$e.'.'); @@ -450,9 +474,16 @@ trait RedisTrait $cleared = true; $hosts = $this->getHosts(); $host = reset($hosts); - if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) { - // Predis supports info command only on the master in replication environments - $hosts = [$host->getClientFor('master')]; + if ($host instanceof \Predis\Client) { + $connection = $host->getConnection(); + + if ($connection instanceof ReplicationInterface) { + $hosts = [$host->getClientFor('master')]; + } elseif ($connection instanceof Predis2ReplicationInterface) { + $connection->switchToMaster(); + + $hosts = [$host]; + } } foreach ($hosts as $host) { @@ -485,7 +516,7 @@ trait RedisTrait $cursor = null; do { - $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor, 'MATCH', $pattern, 'COUNT', 1000) : $host->scan($cursor, $pattern, 1000); + $keys = $host instanceof \Predis\ClientInterface ? $host->scan($cursor ?? 0, 'MATCH', $pattern, 'COUNT', 1000) : $host->scan($cursor, $pattern, 1000); if (isset($keys[1]) && \is_array($keys[1])) { $cursor = $keys[0]; $keys = $keys[1]; @@ -498,7 +529,7 @@ trait RedisTrait } $this->doDelete($keys); } - } while ($cursor = (int) $cursor); + } while ($cursor); } return $cleared; @@ -563,7 +594,7 @@ trait RedisTrait return $failed; } - private function pipeline(\Closure $generator, object $redis = null): \Generator + private function pipeline(\Closure $generator, ?object $redis = null): \Generator { $ids = []; $redis ??= $this->redis; diff --git a/lib/symfony/cache/Traits/Relay/BgsaveTrait.php b/lib/symfony/cache/Traits/Relay/BgsaveTrait.php new file mode 100644 index 000000000..367f82f7b --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/BgsaveTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.11', '>=')) { + /** + * @internal + */ + trait BgsaveTrait + { + public function bgsave($arg = null): \Relay\Relay|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait BgsaveTrait + { + public function bgsave($schedule = false): \Relay\Relay|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/Relay/CopyTrait.php b/lib/symfony/cache/Traits/Relay/CopyTrait.php new file mode 100644 index 000000000..a271a9d10 --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/CopyTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.8.1', '>=')) { + /** + * @internal + */ + trait CopyTrait + { + public function copy($src, $dst, $options = null): \Relay\Relay|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait CopyTrait + { + public function copy($src, $dst, $options = null): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/Relay/GeosearchTrait.php b/lib/symfony/cache/Traits/Relay/GeosearchTrait.php new file mode 100644 index 000000000..88ed1e9d3 --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/GeosearchTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait GeosearchTrait + { + public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait GeosearchTrait + { + public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/Relay/GetrangeTrait.php b/lib/symfony/cache/Traits/Relay/GetrangeTrait.php new file mode 100644 index 000000000..4522d20b5 --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/GetrangeTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait GetrangeTrait + { + public function getrange($key, $start, $end): mixed + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait GetrangeTrait + { + public function getrange($key, $start, $end): \Relay\Relay|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/Relay/HsetTrait.php b/lib/symfony/cache/Traits/Relay/HsetTrait.php new file mode 100644 index 000000000..a7cb8fff0 --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/HsetTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait HsetTrait + { + public function hset($key, ...$keys_and_vals): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait HsetTrait + { + public function hset($key, $mem, $val, ...$kvals): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/Relay/MoveTrait.php b/lib/symfony/cache/Traits/Relay/MoveTrait.php new file mode 100644 index 000000000..d00735ddb --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/MoveTrait.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait MoveTrait + { + public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): mixed + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args()); + } + + public function lmove($srckey, $dstkey, $srcpos, $dstpos): mixed + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait MoveTrait + { + public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): \Relay\Relay|false|null|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args()); + } + + public function lmove($srckey, $dstkey, $srcpos, $dstpos): \Relay\Relay|false|null|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/Relay/NullableReturnTrait.php b/lib/symfony/cache/Traits/Relay/NullableReturnTrait.php new file mode 100644 index 000000000..0b7409045 --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/NullableReturnTrait.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait NullableReturnTrait + { + public function dump($key): \Relay\Relay|false|string|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args()); + } + + public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args()); + } + + public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Relay\Relay|false|string|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args()); + } + + public function zrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args()); + } + + public function zrevrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args()); + } + + public function zscore($key, $member): \Relay\Relay|false|float|null + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait NullableReturnTrait + { + public function dump($key): \Relay\Relay|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); + } + + public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args()); + } + + public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args()); + } + + public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Relay\Relay|false|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args()); + } + + public function zrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args()); + } + + public function zrevrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args()); + } + + public function zscore($key, $member): \Relay\Relay|false|float + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/Relay/PfcountTrait.php b/lib/symfony/cache/Traits/Relay/PfcountTrait.php new file mode 100644 index 000000000..340db8af7 --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/PfcountTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.9.0', '>=')) { + /** + * @internal + */ + trait PfcountTrait + { + public function pfcount($key_or_keys): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait PfcountTrait + { + public function pfcount($key): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args()); + } + } +} diff --git a/lib/symfony/cache/Traits/RelayProxy.php b/lib/symfony/cache/Traits/RelayProxy.php index c55206ead..620eb1ba4 100644 --- a/lib/symfony/cache/Traits/RelayProxy.php +++ b/lib/symfony/cache/Traits/RelayProxy.php @@ -11,6 +11,14 @@ namespace Symfony\Component\Cache\Traits; +use Symfony\Component\Cache\Traits\Relay\BgsaveTrait; +use Symfony\Component\Cache\Traits\Relay\CopyTrait; +use Symfony\Component\Cache\Traits\Relay\GeosearchTrait; +use Symfony\Component\Cache\Traits\Relay\GetrangeTrait; +use Symfony\Component\Cache\Traits\Relay\HsetTrait; +use Symfony\Component\Cache\Traits\Relay\MoveTrait; +use Symfony\Component\Cache\Traits\Relay\NullableReturnTrait; +use Symfony\Component\Cache\Traits\Relay\PfcountTrait; use Symfony\Component\VarExporter\LazyObjectInterface; use Symfony\Component\VarExporter\LazyProxyTrait; use Symfony\Contracts\Service\ResetInterface; @@ -25,9 +33,18 @@ class_exists(\Symfony\Component\VarExporter\Internal\LazyObjectState::class); */ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInterface { + use BgsaveTrait; + use CopyTrait; + use GeosearchTrait; + use GetrangeTrait; + use HsetTrait; use LazyProxyTrait { resetLazyObject as reset; } + use MoveTrait; + use NullableReturnTrait; + use PfcountTrait; + use RelayProxyTrait; private const LAZY_OBJECT_PROPERTY_SCOPES = []; @@ -236,12 +253,12 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->info(...\func_get_args()); } - public function flushdb($async = false): \Relay\Relay|bool + public function flushdb($sync = null): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushdb(...\func_get_args()); } - public function flushall($async = false): \Relay\Relay|bool + public function flushall($sync = null): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->flushall(...\func_get_args()); } @@ -266,16 +283,16 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dbsize(...\func_get_args()); } - public function dump($key): \Relay\Relay|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->dump(...\func_get_args()); - } - public function replicaof($host = null, $port = 0): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->replicaof(...\func_get_args()); } + public function waitaof($numlocal, $numremote, $timeout): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->waitaof(...\func_get_args()); + } + public function restore($key, $ttl, $value, $options = null): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->restore(...\func_get_args()); @@ -286,11 +303,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->migrate(...\func_get_args()); } - public function copy($src, $dst, $options = null): \Relay\Relay|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->copy(...\func_get_args()); - } - public function echo($arg): \Relay\Relay|bool|string { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->echo(...\func_get_args()); @@ -326,9 +338,9 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lastsave(...\func_get_args()); } - public function bgsave($schedule = false): \Relay\Relay|bool + public function lcs($key1, $key2, $options = null): mixed { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->bgsave(...\func_get_args()); + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lcs(...\func_get_args()); } public function save(): \Relay\Relay|bool @@ -386,11 +398,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geoadd(...\func_get_args()); } - public function geodist($key, $src, $dst, $unit = null): \Relay\Relay|false|float - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geodist(...\func_get_args()); - } - public function geohash($key, $member, ...$other_members): \Relay\Relay|array|false { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geohash(...\func_get_args()); @@ -416,11 +423,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->georadius_ro(...\func_get_args()); } - public function geosearch($key, $position, $shape, $unit, $options = []): \Relay\Relay|array - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearch(...\func_get_args()); - } - public function geosearchstore($dst, $src, $position, $shape, $unit, $options = []): \Relay\Relay|false|int { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->geosearchstore(...\func_get_args()); @@ -436,11 +438,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getset(...\func_get_args()); } - public function getrange($key, $start, $end): \Relay\Relay|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->getrange(...\func_get_args()); - } - public function setrange($key, $start, $value): \Relay\Relay|false|int { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->setrange(...\func_get_args()); @@ -521,11 +518,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfadd(...\func_get_args()); } - public function pfcount($key): \Relay\Relay|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfcount(...\func_get_args()); - } - public function pfmerge($dst, $srckeys): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->pfmerge(...\func_get_args()); @@ -636,16 +628,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->type(...\func_get_args()); } - public function lmove($srckey, $dstkey, $srcpos, $dstpos): \Relay\Relay|false|null|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lmove(...\func_get_args()); - } - - public function blmove($srckey, $dstkey, $srcpos, $dstpos, $timeout): \Relay\Relay|false|null|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->blmove(...\func_get_args()); - } - public function lrange($key, $start, $stop): \Relay\Relay|array|false { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->lrange(...\func_get_args()); @@ -801,11 +783,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmget(...\func_get_args()); } - public function hrandfield($hash, $options = null): \Relay\Relay|array|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hrandfield(...\func_get_args()); - } - public function hmset($hash, $members): \Relay\Relay|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hmset(...\func_get_args()); @@ -821,11 +798,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hsetnx(...\func_get_args()); } - public function hset($key, $mem, $val, ...$kvals): \Relay\Relay|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hset(...\func_get_args()); - } - public function hdel($key, $mem, ...$mems): \Relay\Relay|false|int { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hdel(...\func_get_args()); @@ -1091,11 +1063,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xack(...\func_get_args()); } - public function xadd($key, $id, $values, $maxlen = 0, $approx = false, $nomkstream = false): \Relay\Relay|false|string - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xadd(...\func_get_args()); - } - public function xclaim($key, $group, $consumer, $min_idle, $ids, $options): \Relay\Relay|array|bool { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->xclaim(...\func_get_args()); @@ -1201,16 +1168,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrangebylex(...\func_get_args()); } - public function zrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrank(...\func_get_args()); - } - - public function zrevrank($key, $rank, $withscore = false): \Relay\Relay|array|false|int - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrevrank(...\func_get_args()); - } - public function zrem($key, ...$args): \Relay\Relay|false|int { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zrem(...\func_get_args()); @@ -1266,11 +1223,6 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zmscore(...\func_get_args()); } - public function zscore($key, $member): \Relay\Relay|false|float - { - return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zscore(...\func_get_args()); - } - public function zinter($keys, $weights = null, $options = null): \Relay\Relay|array|false { return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->zinter(...\func_get_args()); diff --git a/lib/symfony/cache/Traits/RelayProxyTrait.php b/lib/symfony/cache/Traits/RelayProxyTrait.php new file mode 100644 index 000000000..c35b5fa01 --- /dev/null +++ b/lib/symfony/cache/Traits/RelayProxyTrait.php @@ -0,0 +1,147 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +if (version_compare(phpversion('relay'), '0.8.1', '>=')) { + /** + * @internal + */ + trait RelayProxyTrait + { + public function jsonArrAppend($key, $value_or_array, $path = null): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrAppend(...\func_get_args()); + } + + public function jsonArrIndex($key, $path, $value, $start = 0, $stop = -1): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrIndex(...\func_get_args()); + } + + public function jsonArrInsert($key, $path, $index, $value, ...$other_values): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrInsert(...\func_get_args()); + } + + public function jsonArrLen($key, $path = null): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrLen(...\func_get_args()); + } + + public function jsonArrPop($key, $path = null, $index = -1): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrPop(...\func_get_args()); + } + + public function jsonArrTrim($key, $path, $start, $stop): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonArrTrim(...\func_get_args()); + } + + public function jsonClear($key, $path = null): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonClear(...\func_get_args()); + } + + public function jsonDebug($command, $key, $path = null): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonDebug(...\func_get_args()); + } + + public function jsonDel($key, $path = null): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonDel(...\func_get_args()); + } + + public function jsonForget($key, $path = null): \Relay\Relay|false|int + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonForget(...\func_get_args()); + } + + public function jsonGet($key, $options = [], ...$paths): mixed + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonGet(...\func_get_args()); + } + + public function jsonMerge($key, $path, $value): \Relay\Relay|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonMerge(...\func_get_args()); + } + + public function jsonMget($key_or_array, $path): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonMget(...\func_get_args()); + } + + public function jsonMset($key, $path, $value, ...$other_triples): \Relay\Relay|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonMset(...\func_get_args()); + } + + public function jsonNumIncrBy($key, $path, $value): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonNumIncrBy(...\func_get_args()); + } + + public function jsonNumMultBy($key, $path, $value): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonNumMultBy(...\func_get_args()); + } + + public function jsonObjKeys($key, $path = null): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonObjKeys(...\func_get_args()); + } + + public function jsonObjLen($key, $path = null): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonObjLen(...\func_get_args()); + } + + public function jsonResp($key, $path = null): \Relay\Relay|array|false|int|string + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonResp(...\func_get_args()); + } + + public function jsonSet($key, $path, $value, $condition = null): \Relay\Relay|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonSet(...\func_get_args()); + } + + public function jsonStrAppend($key, $value, $path = null): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonStrAppend(...\func_get_args()); + } + + public function jsonStrLen($key, $path = null): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonStrLen(...\func_get_args()); + } + + public function jsonToggle($key, $path): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonToggle(...\func_get_args()); + } + + public function jsonType($key, $path = null): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->jsonType(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait RelayProxyTrait + { + } +} diff --git a/lib/symfony/config/Builder/ClassBuilder.php b/lib/symfony/config/Builder/ClassBuilder.php index 8194a1526..619ebd857 100644 --- a/lib/symfony/config/Builder/ClassBuilder.php +++ b/lib/symfony/config/Builder/ClassBuilder.php @@ -119,7 +119,7 @@ BODY $this->methods[] = new Method(strtr($body, ['NAME' => $this->camelCase($name)] + $params)); } - public function addProperty(string $name, string $classType = null, string $defaultValue = null): Property + public function addProperty(string $name, ?string $classType = null, ?string $defaultValue = null): Property { $property = new Property($name, '_' !== $name[0] ? $this->camelCase($name) : $name); if (null !== $classType) { diff --git a/lib/symfony/config/Builder/ConfigBuilderGenerator.php b/lib/symfony/config/Builder/ConfigBuilderGenerator.php index d43d814eb..9649c8d82 100644 --- a/lib/symfony/config/Builder/ConfigBuilderGenerator.php +++ b/lib/symfony/config/Builder/ConfigBuilderGenerator.php @@ -413,39 +413,39 @@ public function NAME($value): static { $comment = ''; if ('' !== $info = (string) $node->getInfo()) { - $comment .= ' * '.$info."\n"; + $comment .= $info."\n"; } if (!$node instanceof ArrayNode) { foreach ((array) ($node->getExample() ?? []) as $example) { - $comment .= ' * @example '.$example."\n"; + $comment .= '@example '.$example."\n"; } if ('' !== $default = $node->getDefaultValue()) { - $comment .= ' * @default '.(null === $default ? 'null' : var_export($default, true))."\n"; + $comment .= '@default '.(null === $default ? 'null' : var_export($default, true))."\n"; } if ($node instanceof EnumNode) { - $comment .= sprintf(' * @param ParamConfigurator|%s $value', implode('|', array_unique(array_map(fn ($a) => !$a instanceof \UnitEnum ? var_export($a, true) : '\\'.ltrim(var_export($a, true), '\\'), $node->getValues()))))."\n"; + $comment .= sprintf('@param ParamConfigurator|%s $value', implode('|', array_unique(array_map(fn ($a) => !$a instanceof \UnitEnum ? var_export($a, true) : '\\'.ltrim(var_export($a, true), '\\'), $node->getValues()))))."\n"; } else { $parameterTypes = $this->getParameterTypes($node); - $comment .= ' * @param ParamConfigurator|'.implode('|', $parameterTypes).' $value'."\n"; + $comment .= '@param ParamConfigurator|'.implode('|', $parameterTypes).' $value'."\n"; } } else { foreach ((array) ($node->getExample() ?? []) as $example) { - $comment .= ' * @example '.json_encode($example)."\n"; + $comment .= '@example '.json_encode($example)."\n"; } if ($node->hasDefaultValue() && [] != $default = $node->getDefaultValue()) { - $comment .= ' * @default '.json_encode($default)."\n"; + $comment .= '@default '.json_encode($default)."\n"; } } if ($node->isDeprecated()) { - $comment .= ' * @deprecated '.$node->getDeprecation($node->getName(), $node->getParent()->getName())['message']."\n"; + $comment .= '@deprecated '.$node->getDeprecation($node->getName(), $node->getParent()->getName())['message']."\n"; } - return $comment; + return $comment ? ' * '.str_replace("\n", "\n * ", rtrim($comment, "\n"))."\n" : ''; } /** diff --git a/lib/symfony/config/ConfigCacheInterface.php b/lib/symfony/config/ConfigCacheInterface.php index be7f0986c..f8d270634 100644 --- a/lib/symfony/config/ConfigCacheInterface.php +++ b/lib/symfony/config/ConfigCacheInterface.php @@ -43,5 +43,5 @@ interface ConfigCacheInterface * * @throws \RuntimeException When the cache file cannot be written */ - public function write(string $content, array $metadata = null); + public function write(string $content, ?array $metadata = null); } diff --git a/lib/symfony/config/Definition/BaseNode.php b/lib/symfony/config/Definition/BaseNode.php index 85f0f7eeb..6e2a19227 100644 --- a/lib/symfony/config/Definition/BaseNode.php +++ b/lib/symfony/config/Definition/BaseNode.php @@ -46,7 +46,7 @@ abstract class BaseNode implements NodeInterface /** * @throws \InvalidArgumentException if the name contains a period */ - public function __construct(?string $name, NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR) + public function __construct(?string $name, ?NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR) { if (str_contains($name = (string) $name, $pathSeparator)) { throw new \InvalidArgumentException('The name must not contain ".'.$pathSeparator.'".'); diff --git a/lib/symfony/config/Definition/Builder/ArrayNodeDefinition.php b/lib/symfony/config/Definition/Builder/ArrayNodeDefinition.php index 3ada5c550..7a82334ee 100644 --- a/lib/symfony/config/Definition/Builder/ArrayNodeDefinition.php +++ b/lib/symfony/config/Definition/Builder/ArrayNodeDefinition.php @@ -37,7 +37,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition protected $nodeBuilder; protected $normalizeKeys = true; - public function __construct(?string $name, NodeParentInterface $parent = null) + public function __construct(?string $name, ?NodeParentInterface $parent = null) { parent::__construct($name, $parent); @@ -126,7 +126,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition * * @return $this */ - public function addDefaultChildrenIfNoneSet(int|string|array $children = null): static + public function addDefaultChildrenIfNoneSet(int|string|array|null $children = null): static { $this->addDefaultChildren = $children; @@ -169,7 +169,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition * * @return $this */ - public function fixXmlConfig(string $singular, string $plural = null): static + public function fixXmlConfig(string $singular, ?string $plural = null): static { $this->normalization()->remap($singular, $plural); diff --git a/lib/symfony/config/Definition/Builder/BooleanNodeDefinition.php b/lib/symfony/config/Definition/Builder/BooleanNodeDefinition.php index 3d8fad4d5..15e63961a 100644 --- a/lib/symfony/config/Definition/Builder/BooleanNodeDefinition.php +++ b/lib/symfony/config/Definition/Builder/BooleanNodeDefinition.php @@ -21,7 +21,7 @@ use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException; */ class BooleanNodeDefinition extends ScalarNodeDefinition { - public function __construct(?string $name, NodeParentInterface $parent = null) + public function __construct(?string $name, ?NodeParentInterface $parent = null) { parent::__construct($name, $parent); diff --git a/lib/symfony/config/Definition/Builder/ExprBuilder.php b/lib/symfony/config/Definition/Builder/ExprBuilder.php index 9cb441481..93cdb49dd 100644 --- a/lib/symfony/config/Definition/Builder/ExprBuilder.php +++ b/lib/symfony/config/Definition/Builder/ExprBuilder.php @@ -42,7 +42,7 @@ class ExprBuilder * * @return $this */ - public function always(\Closure $then = null): static + public function always(?\Closure $then = null): static { $this->ifPart = static fn () => true; $this->allowedTypes = self::TYPE_ANY; @@ -61,7 +61,7 @@ class ExprBuilder * * @return $this */ - public function ifTrue(\Closure $closure = null): static + public function ifTrue(?\Closure $closure = null): static { $this->ifPart = $closure ?? static fn ($v) => true === $v; $this->allowedTypes = self::TYPE_ANY; diff --git a/lib/symfony/config/Definition/Builder/NodeBuilder.php b/lib/symfony/config/Definition/Builder/NodeBuilder.php index 7cda0bc7d..93069d437 100644 --- a/lib/symfony/config/Definition/Builder/NodeBuilder.php +++ b/lib/symfony/config/Definition/Builder/NodeBuilder.php @@ -39,7 +39,7 @@ class NodeBuilder implements NodeParentInterface * * @return $this */ - public function setParent(ParentNodeDefinitionInterface $parent = null): static + public function setParent(?ParentNodeDefinitionInterface $parent = null): static { if (1 > \func_num_args()) { trigger_deprecation('symfony/form', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); diff --git a/lib/symfony/config/Definition/Builder/NodeDefinition.php b/lib/symfony/config/Definition/Builder/NodeDefinition.php index 2c93a0f7d..cf2173e17 100644 --- a/lib/symfony/config/Definition/Builder/NodeDefinition.php +++ b/lib/symfony/config/Definition/Builder/NodeDefinition.php @@ -38,7 +38,7 @@ abstract class NodeDefinition implements NodeParentInterface protected $parent; protected $attributes = []; - public function __construct(?string $name, NodeParentInterface $parent = null) + public function __construct(?string $name, ?NodeParentInterface $parent = null) { $this->parent = $parent; $this->name = $name; diff --git a/lib/symfony/config/Definition/Builder/NormalizationBuilder.php b/lib/symfony/config/Definition/Builder/NormalizationBuilder.php index 0e362d9fa..1f6b34441 100644 --- a/lib/symfony/config/Definition/Builder/NormalizationBuilder.php +++ b/lib/symfony/config/Definition/Builder/NormalizationBuilder.php @@ -36,7 +36,7 @@ class NormalizationBuilder * * @return $this */ - public function remap(string $key, string $plural = null): static + public function remap(string $key, ?string $plural = null): static { $this->remappings[] = [$key, null === $plural ? $key.'s' : $plural]; @@ -48,7 +48,7 @@ class NormalizationBuilder * * @return ExprBuilder|$this */ - public function before(\Closure $closure = null): ExprBuilder|static + public function before(?\Closure $closure = null): ExprBuilder|static { if (null !== $closure) { $this->before[] = $closure; diff --git a/lib/symfony/config/Definition/Builder/TreeBuilder.php b/lib/symfony/config/Definition/Builder/TreeBuilder.php index cdee55772..f7da3e794 100644 --- a/lib/symfony/config/Definition/Builder/TreeBuilder.php +++ b/lib/symfony/config/Definition/Builder/TreeBuilder.php @@ -30,7 +30,7 @@ class TreeBuilder implements NodeParentInterface */ protected $root; - public function __construct(string $name, string $type = 'array', NodeBuilder $builder = null) + public function __construct(string $name, string $type = 'array', ?NodeBuilder $builder = null) { $builder ??= new NodeBuilder(); $this->root = $builder->node($name, $type)->setParent($this); diff --git a/lib/symfony/config/Definition/Builder/ValidationBuilder.php b/lib/symfony/config/Definition/Builder/ValidationBuilder.php index 1bee851b6..64623d6d6 100644 --- a/lib/symfony/config/Definition/Builder/ValidationBuilder.php +++ b/lib/symfony/config/Definition/Builder/ValidationBuilder.php @@ -31,7 +31,7 @@ class ValidationBuilder * * @return ExprBuilder|$this */ - public function rule(\Closure $closure = null): ExprBuilder|static + public function rule(?\Closure $closure = null): ExprBuilder|static { if (null !== $closure) { $this->rules[] = $closure; diff --git a/lib/symfony/config/Definition/Configurator/DefinitionConfigurator.php b/lib/symfony/config/Definition/Configurator/DefinitionConfigurator.php index 006a444be..13fe45ca4 100644 --- a/lib/symfony/config/Definition/Configurator/DefinitionConfigurator.php +++ b/lib/symfony/config/Definition/Configurator/DefinitionConfigurator.php @@ -29,7 +29,7 @@ class DefinitionConfigurator ) { } - public function import(string $resource, string $type = null, bool $ignoreErrors = false): void + public function import(string $resource, ?string $type = null, bool $ignoreErrors = false): void { $this->loader->setCurrentDir(\dirname($this->path)); $this->loader->import($resource, $type, $ignoreErrors, $this->file); diff --git a/lib/symfony/config/Definition/Dumper/XmlReferenceDumper.php b/lib/symfony/config/Definition/Dumper/XmlReferenceDumper.php index 34f93ce07..aac2d8456 100644 --- a/lib/symfony/config/Definition/Dumper/XmlReferenceDumper.php +++ b/lib/symfony/config/Definition/Dumper/XmlReferenceDumper.php @@ -34,7 +34,7 @@ class XmlReferenceDumper /** * @return string */ - public function dump(ConfigurationInterface $configuration, string $namespace = null) + public function dump(ConfigurationInterface $configuration, ?string $namespace = null) { return $this->dumpNode($configuration->getConfigTreeBuilder()->buildTree(), $namespace); } @@ -42,7 +42,7 @@ class XmlReferenceDumper /** * @return string */ - public function dumpNode(NodeInterface $node, string $namespace = null) + public function dumpNode(NodeInterface $node, ?string $namespace = null) { $this->reference = ''; $this->writeNode($node, 0, true, $namespace); @@ -52,7 +52,7 @@ class XmlReferenceDumper return $ref; } - private function writeNode(NodeInterface $node, int $depth = 0, bool $root = false, string $namespace = null): void + private function writeNode(NodeInterface $node, int $depth = 0, bool $root = false, ?string $namespace = null): void { $rootName = ($root ? 'config' : $node->getName()); $rootNamespace = ($namespace ?: ($root ? 'http://example.org/schema/dic/'.$node->getName() : null)); diff --git a/lib/symfony/config/Definition/Dumper/YamlReferenceDumper.php b/lib/symfony/config/Definition/Dumper/YamlReferenceDumper.php index 97a391ada..abcf1bd9e 100644 --- a/lib/symfony/config/Definition/Dumper/YamlReferenceDumper.php +++ b/lib/symfony/config/Definition/Dumper/YamlReferenceDumper.php @@ -18,7 +18,6 @@ use Symfony\Component\Config\Definition\EnumNode; use Symfony\Component\Config\Definition\NodeInterface; use Symfony\Component\Config\Definition\PrototypedArrayNode; use Symfony\Component\Config\Definition\ScalarNode; -use Symfony\Component\Config\Definition\VariableNode; use Symfony\Component\Yaml\Inline; /** @@ -80,7 +79,7 @@ class YamlReferenceDumper return $ref; } - private function writeNode(NodeInterface $node, NodeInterface $parentNode = null, int $depth = 0, bool $prototypedArray = false): void + private function writeNode(NodeInterface $node, ?NodeInterface $parentNode = null, int $depth = 0, bool $prototypedArray = false): void { $comments = []; $default = ''; @@ -99,19 +98,12 @@ class YamlReferenceDumper $children = $this->getPrototypeChildren($node); } - if (!$children) { - if ($node->hasDefaultValue() && \count($defaultArray = $node->getDefaultValue())) { - $default = ''; - } elseif (!\is_array($example)) { - $default = '[]'; - } + if (!$children && !($node->hasDefaultValue() && \count($defaultArray = $node->getDefaultValue()))) { + $default = '[]'; } } elseif ($node instanceof EnumNode) { $comments[] = 'One of '.$node->getPermissibleValues('; '); $default = $node->hasDefaultValue() ? Inline::dump($node->getDefaultValue()) : '~'; - } elseif (VariableNode::class === $node::class && \is_array($example)) { - // If there is an array example, we are sure we dont need to print a default value - $default = ''; } else { $default = '~'; @@ -179,7 +171,7 @@ class YamlReferenceDumper $this->writeLine('# '.$message.':', $depth * 4 + 4); - $this->writeArray(array_map(Inline::dump(...), $example), $depth + 1); + $this->writeArray(array_map(Inline::dump(...), $example), $depth + 1, true); } if ($children) { @@ -200,7 +192,7 @@ class YamlReferenceDumper $this->reference .= sprintf($format, $text)."\n"; } - private function writeArray(array $array, int $depth): void + private function writeArray(array $array, int $depth, bool $asComment = false): void { $isIndexed = array_is_list($array); @@ -211,14 +203,16 @@ class YamlReferenceDumper $val = $value; } + $prefix = $asComment ? '# ' : ''; + if ($isIndexed) { - $this->writeLine('- '.$val, $depth * 4); + $this->writeLine($prefix.'- '.$val, $depth * 4); } else { - $this->writeLine(sprintf('%-20s %s', $key.':', $val), $depth * 4); + $this->writeLine(sprintf('%s%-20s %s', $prefix, $key.':', $val), $depth * 4); } if (\is_array($value)) { - $this->writeArray($value, $depth + 1); + $this->writeArray($value, $depth + 1, $asComment); } } } diff --git a/lib/symfony/config/Definition/EnumNode.php b/lib/symfony/config/Definition/EnumNode.php index 4edeae904..f5acbe906 100644 --- a/lib/symfony/config/Definition/EnumNode.php +++ b/lib/symfony/config/Definition/EnumNode.php @@ -22,7 +22,7 @@ class EnumNode extends ScalarNode { private array $values; - public function __construct(?string $name, NodeInterface $parent = null, array $values = [], string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) + public function __construct(?string $name, ?NodeInterface $parent = null, array $values = [], string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) { if (!$values) { throw new \InvalidArgumentException('$values must contain at least one element.'); diff --git a/lib/symfony/config/Definition/Loader/DefinitionFileLoader.php b/lib/symfony/config/Definition/Loader/DefinitionFileLoader.php index 506f787ca..940b894f7 100644 --- a/lib/symfony/config/Definition/Loader/DefinitionFileLoader.php +++ b/lib/symfony/config/Definition/Loader/DefinitionFileLoader.php @@ -34,7 +34,7 @@ class DefinitionFileLoader extends FileLoader parent::__construct($locator); } - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { // the loader variable is exposed to the included file below $loader = $this; @@ -57,7 +57,7 @@ class DefinitionFileLoader extends FileLoader return null; } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { if (!\is_string($resource)) { return false; diff --git a/lib/symfony/config/Definition/NumericNode.php b/lib/symfony/config/Definition/NumericNode.php index da32b843a..22359fd25 100644 --- a/lib/symfony/config/Definition/NumericNode.php +++ b/lib/symfony/config/Definition/NumericNode.php @@ -23,7 +23,7 @@ class NumericNode extends ScalarNode protected $min; protected $max; - public function __construct(?string $name, NodeInterface $parent = null, int|float $min = null, int|float $max = null, string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) + public function __construct(?string $name, ?NodeInterface $parent = null, int|float|null $min = null, int|float|null $max = null, string $pathSeparator = BaseNode::DEFAULT_PATH_SEPARATOR) { parent::__construct($name, $parent, $pathSeparator); $this->min = $min; diff --git a/lib/symfony/config/Definition/Processor.php b/lib/symfony/config/Definition/Processor.php index dc3d4c69b..272ddcc44 100644 --- a/lib/symfony/config/Definition/Processor.php +++ b/lib/symfony/config/Definition/Processor.php @@ -67,7 +67,7 @@ class Processor * @param string $key The key to normalize * @param string|null $plural The plural form of the key if it is irregular */ - public static function normalizeConfig(array $config, string $key, string $plural = null): array + public static function normalizeConfig(array $config, string $key, ?string $plural = null): array { $plural ??= $key.'s'; diff --git a/lib/symfony/config/Exception/FileLoaderImportCircularReferenceException.php b/lib/symfony/config/Exception/FileLoaderImportCircularReferenceException.php index da0b55ba8..2d2a4de00 100644 --- a/lib/symfony/config/Exception/FileLoaderImportCircularReferenceException.php +++ b/lib/symfony/config/Exception/FileLoaderImportCircularReferenceException.php @@ -18,7 +18,7 @@ namespace Symfony\Component\Config\Exception; */ class FileLoaderImportCircularReferenceException extends LoaderLoadException { - public function __construct(array $resources, int $code = 0, \Throwable $previous = null) + public function __construct(array $resources, int $code = 0, ?\Throwable $previous = null) { $message = sprintf('Circular reference detected in "%s" ("%s" > "%s").', $this->varToString($resources[0]), implode('" > "', $resources), $resources[0]); diff --git a/lib/symfony/config/Exception/FileLocatorFileNotFoundException.php b/lib/symfony/config/Exception/FileLocatorFileNotFoundException.php index c5173ae58..a3fcc901b 100644 --- a/lib/symfony/config/Exception/FileLocatorFileNotFoundException.php +++ b/lib/symfony/config/Exception/FileLocatorFileNotFoundException.php @@ -20,7 +20,7 @@ class FileLocatorFileNotFoundException extends \InvalidArgumentException { private array $paths; - public function __construct(string $message = '', int $code = 0, \Throwable $previous = null, array $paths = []) + public function __construct(string $message = '', int $code = 0, ?\Throwable $previous = null, array $paths = []) { parent::__construct($message, $code, $previous); diff --git a/lib/symfony/config/Exception/LoaderLoadException.php b/lib/symfony/config/Exception/LoaderLoadException.php index 57afd6a8d..2b40688a5 100644 --- a/lib/symfony/config/Exception/LoaderLoadException.php +++ b/lib/symfony/config/Exception/LoaderLoadException.php @@ -25,7 +25,7 @@ class LoaderLoadException extends \Exception * @param \Throwable|null $previous A previous exception * @param string|null $type The type of resource */ - public function __construct(mixed $resource, string $sourceResource = null, int $code = 0, \Throwable $previous = null, string $type = null) + public function __construct(mixed $resource, ?string $sourceResource = null, int $code = 0, ?\Throwable $previous = null, ?string $type = null) { if (!\is_string($resource)) { try { diff --git a/lib/symfony/config/FileLocator.php b/lib/symfony/config/FileLocator.php index e147d9b1a..7f85367d0 100644 --- a/lib/symfony/config/FileLocator.php +++ b/lib/symfony/config/FileLocator.php @@ -31,9 +31,11 @@ class FileLocator implements FileLocatorInterface } /** - * @return string|array + * @return string|string[] + * + * @psalm-return ($first is true ? string : string[]) */ - public function locate(string $name, string $currentPath = null, bool $first = true) + public function locate(string $name, ?string $currentPath = null, bool $first = true) { if ('' === $name) { throw new \InvalidArgumentException('An empty file name is not valid to be located.'); @@ -84,7 +86,8 @@ class FileLocator implements FileLocatorInterface && ':' === $file[1] && ('\\' === $file[2] || '/' === $file[2]) ) - || null !== parse_url($file, \PHP_URL_SCHEME) + || parse_url($file, \PHP_URL_SCHEME) + || str_starts_with($file, 'phar:///') // "parse_url()" doesn't handle absolute phar path, despite being valid ) { return true; } diff --git a/lib/symfony/config/FileLocatorInterface.php b/lib/symfony/config/FileLocatorInterface.php index e3ca1d49c..755cf018a 100644 --- a/lib/symfony/config/FileLocatorInterface.php +++ b/lib/symfony/config/FileLocatorInterface.php @@ -25,10 +25,12 @@ interface FileLocatorInterface * @param string|null $currentPath The current path * @param bool $first Whether to return the first occurrence or an array of filenames * - * @return string|array The full path to the file or an array of file paths + * @return string|string[] The full path to the file or an array of file paths * * @throws \InvalidArgumentException If $name is empty * @throws FileLocatorFileNotFoundException If a file is not found + * + * @psalm-return ($first is true ? string : string[]) */ - public function locate(string $name, string $currentPath = null, bool $first = true); + public function locate(string $name, ?string $currentPath = null, bool $first = true); } diff --git a/lib/symfony/config/Loader/DelegatingLoader.php b/lib/symfony/config/Loader/DelegatingLoader.php index fac3724e9..045a559e2 100644 --- a/lib/symfony/config/Loader/DelegatingLoader.php +++ b/lib/symfony/config/Loader/DelegatingLoader.php @@ -28,7 +28,7 @@ class DelegatingLoader extends Loader $this->resolver = $resolver; } - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { if (false === $loader = $this->resolver->resolve($resource, $type)) { throw new LoaderLoadException($resource, null, 0, null, $type); @@ -37,7 +37,7 @@ class DelegatingLoader extends Loader return $loader->load($resource, $type); } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { return false !== $this->resolver->resolve($resource, $type); } diff --git a/lib/symfony/config/Loader/FileLoader.php b/lib/symfony/config/Loader/FileLoader.php index 8cfaa23ba..8275ffcd3 100644 --- a/lib/symfony/config/Loader/FileLoader.php +++ b/lib/symfony/config/Loader/FileLoader.php @@ -31,7 +31,7 @@ abstract class FileLoader extends Loader private ?string $currentDir = null; - public function __construct(FileLocatorInterface $locator, string $env = null) + public function __construct(FileLocatorInterface $locator, ?string $env = null) { $this->locator = $locator; parent::__construct($env); @@ -70,7 +70,7 @@ abstract class FileLoader extends Loader * @throws FileLoaderImportCircularReferenceException * @throws FileLocatorFileNotFoundException */ - public function import(mixed $resource, string $type = null, bool $ignoreErrors = false, string $sourceResource = null, string|array $exclude = null) + public function import(mixed $resource, ?string $type = null, bool $ignoreErrors = false, ?string $sourceResource = null, string|array|null $exclude = null) { if (\is_string($resource) && \strlen($resource) !== ($i = strcspn($resource, '*?{[')) && !str_contains($resource, "\n")) { $excluded = []; @@ -101,7 +101,7 @@ abstract class FileLoader extends Loader /** * @internal */ - protected function glob(string $pattern, bool $recursive, array|GlobResource &$resource = null, bool $ignoreErrors = false, bool $forExclusion = false, array $excluded = []): iterable + protected function glob(string $pattern, bool $recursive, array|GlobResource|null &$resource = null, bool $ignoreErrors = false, bool $forExclusion = false, array $excluded = []): iterable { if (\strlen($pattern) === $i = strcspn($pattern, '*?{[')) { $prefix = $pattern; @@ -133,7 +133,7 @@ abstract class FileLoader extends Loader yield from $resource; } - private function doImport(mixed $resource, string $type = null, bool $ignoreErrors = false, string $sourceResource = null): mixed + private function doImport(mixed $resource, ?string $type = null, bool $ignoreErrors = false, ?string $sourceResource = null): mixed { try { $loader = $this->resolve($resource, $type); diff --git a/lib/symfony/config/Loader/GlobFileLoader.php b/lib/symfony/config/Loader/GlobFileLoader.php index f921ec555..31eebf69d 100644 --- a/lib/symfony/config/Loader/GlobFileLoader.php +++ b/lib/symfony/config/Loader/GlobFileLoader.php @@ -18,12 +18,12 @@ namespace Symfony\Component\Config\Loader; */ class GlobFileLoader extends FileLoader { - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { return $this->import($resource); } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { return 'glob' === $type; } diff --git a/lib/symfony/config/Loader/Loader.php b/lib/symfony/config/Loader/Loader.php index 36e85ad34..66c38bbea 100644 --- a/lib/symfony/config/Loader/Loader.php +++ b/lib/symfony/config/Loader/Loader.php @@ -23,7 +23,7 @@ abstract class Loader implements LoaderInterface protected $resolver; protected $env; - public function __construct(string $env = null) + public function __construct(?string $env = null) { $this->env = $env; } @@ -46,7 +46,7 @@ abstract class Loader implements LoaderInterface * * @return mixed */ - public function import(mixed $resource, string $type = null) + public function import(mixed $resource, ?string $type = null) { return $this->resolve($resource, $type)->load($resource, $type); } @@ -56,7 +56,7 @@ abstract class Loader implements LoaderInterface * * @throws LoaderLoadException If no loader is found */ - public function resolve(mixed $resource, string $type = null): LoaderInterface + public function resolve(mixed $resource, ?string $type = null): LoaderInterface { if ($this->supports($resource, $type)) { return $this; diff --git a/lib/symfony/config/Loader/LoaderInterface.php b/lib/symfony/config/Loader/LoaderInterface.php index 4e0746d4d..190d2c630 100644 --- a/lib/symfony/config/Loader/LoaderInterface.php +++ b/lib/symfony/config/Loader/LoaderInterface.php @@ -25,7 +25,7 @@ interface LoaderInterface * * @throws \Exception If something went wrong */ - public function load(mixed $resource, string $type = null); + public function load(mixed $resource, ?string $type = null); /** * Returns whether this class supports the given resource. @@ -34,7 +34,7 @@ interface LoaderInterface * * @return bool */ - public function supports(mixed $resource, string $type = null); + public function supports(mixed $resource, ?string $type = null); /** * Gets the loader resolver. diff --git a/lib/symfony/config/Loader/LoaderResolver.php b/lib/symfony/config/Loader/LoaderResolver.php index 670e32012..72ab33411 100644 --- a/lib/symfony/config/Loader/LoaderResolver.php +++ b/lib/symfony/config/Loader/LoaderResolver.php @@ -36,7 +36,7 @@ class LoaderResolver implements LoaderResolverInterface } } - public function resolve(mixed $resource, string $type = null): LoaderInterface|false + public function resolve(mixed $resource, ?string $type = null): LoaderInterface|false { foreach ($this->loaders as $loader) { if ($loader->supports($resource, $type)) { diff --git a/lib/symfony/config/Loader/LoaderResolverInterface.php b/lib/symfony/config/Loader/LoaderResolverInterface.php index 076c5207c..a8bb3a437 100644 --- a/lib/symfony/config/Loader/LoaderResolverInterface.php +++ b/lib/symfony/config/Loader/LoaderResolverInterface.php @@ -23,5 +23,5 @@ interface LoaderResolverInterface * * @param string|null $type The resource type or null if unknown */ - public function resolve(mixed $resource, string $type = null): LoaderInterface|false; + public function resolve(mixed $resource, ?string $type = null): LoaderInterface|false; } diff --git a/lib/symfony/config/Resource/ClassExistenceResource.php b/lib/symfony/config/Resource/ClassExistenceResource.php index cae3877ad..eab04b8d0 100644 --- a/lib/symfony/config/Resource/ClassExistenceResource.php +++ b/lib/symfony/config/Resource/ClassExistenceResource.php @@ -34,7 +34,7 @@ class ClassExistenceResource implements SelfCheckingResourceInterface * @param string $resource The fully-qualified class name * @param bool|null $exists Boolean when the existence check has already been done */ - public function __construct(string $resource, bool $exists = null) + public function __construct(string $resource, ?bool $exists = null) { $this->resource = $resource; if (null !== $exists) { @@ -139,7 +139,7 @@ class ClassExistenceResource implements SelfCheckingResourceInterface * * @internal */ - public static function throwOnRequiredClass(string $class, \Exception $previous = null): void + public static function throwOnRequiredClass(string $class, ?\Exception $previous = null): void { // If the passed class is the resource being checked, we shouldn't throw. if (null === $previous && self::$autoloadedClass === $class) { diff --git a/lib/symfony/config/Resource/DirectoryResource.php b/lib/symfony/config/Resource/DirectoryResource.php index 7560cd3b3..df486a085 100644 --- a/lib/symfony/config/Resource/DirectoryResource.php +++ b/lib/symfony/config/Resource/DirectoryResource.php @@ -29,7 +29,7 @@ class DirectoryResource implements SelfCheckingResourceInterface * * @throws \InvalidArgumentException */ - public function __construct(string $resource, string $pattern = null) + public function __construct(string $resource, ?string $pattern = null) { $resolvedResource = realpath($resource) ?: (file_exists($resource) ? $resource : false); $this->pattern = $pattern; diff --git a/lib/symfony/config/ResourceCheckerConfigCache.php b/lib/symfony/config/ResourceCheckerConfigCache.php index a8478a8cc..1e58d21ed 100644 --- a/lib/symfony/config/ResourceCheckerConfigCache.php +++ b/lib/symfony/config/ResourceCheckerConfigCache.php @@ -109,7 +109,7 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface * * @throws \RuntimeException When cache file can't be written */ - public function write(string $content, array $metadata = null) + public function write(string $content, ?array $metadata = null) { $mode = 0666; $umask = umask(); @@ -150,7 +150,7 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface $signalingException = new \UnexpectedValueException(); $prevUnserializeHandler = ini_set('unserialize_callback_func', self::class.'::handleUnserializeCallback'); $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler, $signalingException) { - if (__FILE__ === $file) { + if (__FILE__ === $file && !\in_array($type, [\E_DEPRECATED, \E_USER_DEPRECATED], true)) { throw $signalingException; } diff --git a/lib/symfony/config/Util/XmlUtils.php b/lib/symfony/config/Util/XmlUtils.php index cc024da46..eb6f0f51a 100644 --- a/lib/symfony/config/Util/XmlUtils.php +++ b/lib/symfony/config/Util/XmlUtils.php @@ -42,7 +42,7 @@ class XmlUtils * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself * @throws \RuntimeException When DOM extension is missing */ - public static function parse(string $content, string|callable $schemaOrCallable = null): \DOMDocument + public static function parse(string $content, string|callable|null $schemaOrCallable = null): \DOMDocument { if (!\extension_loaded('dom')) { throw new \LogicException('Extension DOM is required.'); @@ -112,7 +112,7 @@ class XmlUtils * @throws XmlParsingException When XML parsing returns any errors * @throws \RuntimeException When DOM extension is missing */ - public static function loadFile(string $file, string|callable $schemaOrCallable = null): \DOMDocument + public static function loadFile(string $file, string|callable|null $schemaOrCallable = null): \DOMDocument { if (!is_file($file)) { throw new \InvalidArgumentException(sprintf('Resource "%s" is not a file.', $file)); diff --git a/lib/symfony/console/Application.php b/lib/symfony/console/Application.php index 01b6a373d..b876bc971 100644 --- a/lib/symfony/console/Application.php +++ b/lib/symfony/console/Application.php @@ -143,7 +143,7 @@ class Application implements ResetInterface * * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}. */ - public function run(InputInterface $input = null, OutputInterface $output = null): int + public function run(?InputInterface $input = null, ?OutputInterface $output = null): int { if (\function_exists('putenv')) { @putenv('LINES='.$this->terminal->getHeight()); @@ -169,9 +169,9 @@ class Application implements ResetInterface } } - $this->configureIO($input, $output); - try { + $this->configureIO($input, $output); + $exitCode = $this->doRun($input, $output); } catch (\Throwable $e) { if ($e instanceof \Exception && !$this->catchExceptions) { @@ -795,7 +795,7 @@ class Application implements ResetInterface * * @return Command[] */ - public function all(string $namespace = null) + public function all(?string $namespace = null) { $this->init(); @@ -875,7 +875,7 @@ class Application implements ResetInterface } if (str_contains($message, "@anonymous\0")) { - $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $message); + $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $message); } $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX; @@ -1177,7 +1177,7 @@ class Application implements ResetInterface * * This method is not part of public API and should not be used directly. */ - public function extractNamespace(string $name, int $limit = null): string + public function extractNamespace(string $name, ?int $limit = null): string { $parts = explode(':', $name, -1); @@ -1278,7 +1278,7 @@ class Application implements ResetInterface foreach (preg_split('//u', $m[0]) as $char) { // test if $char could be appended to current line - if (mb_strwidth($line.$char, 'utf8') <= $width) { + if (Helper::width($line.$char) <= $width) { $line .= $char; continue; } diff --git a/lib/symfony/console/CI/GithubActionReporter.php b/lib/symfony/console/CI/GithubActionReporter.php index 7e5565469..2cae6fd8b 100644 --- a/lib/symfony/console/CI/GithubActionReporter.php +++ b/lib/symfony/console/CI/GithubActionReporter.php @@ -57,7 +57,7 @@ class GithubActionReporter * * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message */ - public function error(string $message, string $file = null, int $line = null, int $col = null): void + public function error(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void { $this->log('error', $message, $file, $line, $col); } @@ -67,7 +67,7 @@ class GithubActionReporter * * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message */ - public function warning(string $message, string $file = null, int $line = null, int $col = null): void + public function warning(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void { $this->log('warning', $message, $file, $line, $col); } @@ -77,12 +77,12 @@ class GithubActionReporter * * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message */ - public function debug(string $message, string $file = null, int $line = null, int $col = null): void + public function debug(string $message, ?string $file = null, ?int $line = null, ?int $col = null): void { $this->log('debug', $message, $file, $line, $col); } - private function log(string $type, string $message, string $file = null, int $line = null, int $col = null): void + private function log(string $type, string $message, ?string $file = null, ?int $line = null, ?int $col = null): void { // Some values must be encoded. $message = strtr($message, self::ESCAPED_DATA); diff --git a/lib/symfony/console/Command/Command.php b/lib/symfony/console/Command/Command.php index 704b112d1..9f9cb2f53 100644 --- a/lib/symfony/console/Command/Command.php +++ b/lib/symfony/console/Command/Command.php @@ -111,7 +111,7 @@ class Command * * @throws LogicException When the command name is empty */ - public function __construct(string $name = null) + public function __construct(?string $name = null) { $this->definition = new InputDefinition(); @@ -152,7 +152,7 @@ class Command /** * @return void */ - public function setApplication(Application $application = null) + public function setApplication(?Application $application = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -460,7 +460,7 @@ class Command * * @throws InvalidArgumentException When argument mode is not valid */ - public function addArgument(string $name, int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = null */): static + public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = null */): static { $suggestedValues = 5 <= \func_num_args() ? func_get_arg(4) : []; if (!\is_array($suggestedValues) && !$suggestedValues instanceof \Closure) { @@ -484,7 +484,7 @@ class Command * * @throws InvalidArgumentException If option mode is invalid or incompatible */ - public function addOption(string $name, string|array $shortcut = null, int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static + public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static { $suggestedValues = 6 <= \func_num_args() ? func_get_arg(5) : []; if (!\is_array($suggestedValues) && !$suggestedValues instanceof \Closure) { diff --git a/lib/symfony/console/Command/LazyCommand.php b/lib/symfony/console/Command/LazyCommand.php index d56058221..b94da6665 100644 --- a/lib/symfony/console/Command/LazyCommand.php +++ b/lib/symfony/console/Command/LazyCommand.php @@ -45,7 +45,7 @@ final class LazyCommand extends Command $this->getCommand()->ignoreValidationErrors(); } - public function setApplication(Application $application = null): void + public function setApplication(?Application $application = null): void { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -116,7 +116,7 @@ final class LazyCommand extends Command /** * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion */ - public function addArgument(string $name, int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static + public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static { $suggestedValues = 5 <= \func_num_args() ? func_get_arg(4) : []; $this->getCommand()->addArgument($name, $mode, $description, $default, $suggestedValues); @@ -127,7 +127,7 @@ final class LazyCommand extends Command /** * @param array|\Closure(CompletionInput,CompletionSuggestions):list $suggestedValues The values used for input completion */ - public function addOption(string $name, string|array $shortcut = null, int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static + public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null /* array|\Closure $suggestedValues = [] */): static { $suggestedValues = 6 <= \func_num_args() ? func_get_arg(5) : []; $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues); diff --git a/lib/symfony/console/Command/LockableTrait.php b/lib/symfony/console/Command/LockableTrait.php index c1006a65c..cd7548f02 100644 --- a/lib/symfony/console/Command/LockableTrait.php +++ b/lib/symfony/console/Command/LockableTrait.php @@ -29,7 +29,7 @@ trait LockableTrait /** * Locks a command. */ - private function lock(string $name = null, bool $blocking = false): bool + private function lock(?string $name = null, bool $blocking = false): bool { if (!class_exists(SemaphoreStore::class)) { throw new LogicException('To enable the locking feature you must install the symfony/lock component. Try running "composer require symfony/lock".'); diff --git a/lib/symfony/console/Command/TraceableCommand.php b/lib/symfony/console/Command/TraceableCommand.php index d8c46b7fa..9ffb68da3 100644 --- a/lib/symfony/console/Command/TraceableCommand.php +++ b/lib/symfony/console/Command/TraceableCommand.php @@ -134,7 +134,7 @@ final class TraceableCommand extends Command implements SignalableCommandInterfa parent::ignoreValidationErrors(); } - public function setApplication(Application $application = null): void + public function setApplication(?Application $application = null): void { $this->command->setApplication($application); } @@ -209,14 +209,14 @@ final class TraceableCommand extends Command implements SignalableCommandInterfa return $this->command->getNativeDefinition(); } - public function addArgument(string $name, int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static + public function addArgument(string $name, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static { $this->command->addArgument($name, $mode, $description, $default, $suggestedValues); return $this; } - public function addOption(string $name, string|array $shortcut = null, int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static + public function addOption(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', mixed $default = null, array|\Closure $suggestedValues = []): static { $this->command->addOption($name, $shortcut, $mode, $description, $default, $suggestedValues); diff --git a/lib/symfony/console/Completion/CompletionInput.php b/lib/symfony/console/Completion/CompletionInput.php index 7ba41c083..79c2f659a 100644 --- a/lib/symfony/console/Completion/CompletionInput.php +++ b/lib/symfony/console/Completion/CompletionInput.php @@ -53,7 +53,7 @@ final class CompletionInput extends ArgvInput * Create an input based on an COMP_WORDS token list. * * @param string[] $tokens the set of split tokens (e.g. COMP_WORDS or argv) - * @param $currentIndex the index of the cursor (e.g. COMP_CWORD) + * @param int $currentIndex the index of the cursor (e.g. COMP_CWORD) */ public static function fromTokens(array $tokens, int $currentIndex): self { diff --git a/lib/symfony/console/DataCollector/CommandDataCollector.php b/lib/symfony/console/DataCollector/CommandDataCollector.php index 16a0eadf4..45138c7dc 100644 --- a/lib/symfony/console/DataCollector/CommandDataCollector.php +++ b/lib/symfony/console/DataCollector/CommandDataCollector.php @@ -27,7 +27,7 @@ use Symfony\Component\VarDumper\Cloner\Data; */ final class CommandDataCollector extends DataCollector { - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { if (!$request instanceof CliRequest) { return; diff --git a/lib/symfony/console/Descriptor/ApplicationDescription.php b/lib/symfony/console/Descriptor/ApplicationDescription.php index f8ed18045..ef9e8a63b 100644 --- a/lib/symfony/console/Descriptor/ApplicationDescription.php +++ b/lib/symfony/console/Descriptor/ApplicationDescription.php @@ -39,7 +39,7 @@ class ApplicationDescription */ private array $aliases = []; - public function __construct(Application $application, string $namespace = null, bool $showHidden = false) + public function __construct(Application $application, ?string $namespace = null, bool $showHidden = false) { $this->application = $application; $this->namespace = $namespace; diff --git a/lib/symfony/console/Descriptor/XmlDescriptor.php b/lib/symfony/console/Descriptor/XmlDescriptor.php index 72580fd98..866c71856 100644 --- a/lib/symfony/console/Descriptor/XmlDescriptor.php +++ b/lib/symfony/console/Descriptor/XmlDescriptor.php @@ -79,7 +79,7 @@ class XmlDescriptor extends Descriptor return $dom; } - public function getApplicationDocument(Application $application, string $namespace = null, bool $short = false): \DOMDocument + public function getApplicationDocument(Application $application, ?string $namespace = null, bool $short = false): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); diff --git a/lib/symfony/console/Event/ConsoleErrorEvent.php b/lib/symfony/console/Event/ConsoleErrorEvent.php index d4a691216..7be2ff83e 100644 --- a/lib/symfony/console/Event/ConsoleErrorEvent.php +++ b/lib/symfony/console/Event/ConsoleErrorEvent.php @@ -25,7 +25,7 @@ final class ConsoleErrorEvent extends ConsoleEvent private \Throwable $error; private int $exitCode; - public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null) + public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, ?Command $command = null) { parent::__construct($command, $input, $output); diff --git a/lib/symfony/console/EventListener/ErrorListener.php b/lib/symfony/console/EventListener/ErrorListener.php index 9925a5f74..c9ec24434 100644 --- a/lib/symfony/console/EventListener/ErrorListener.php +++ b/lib/symfony/console/EventListener/ErrorListener.php @@ -26,7 +26,7 @@ class ErrorListener implements EventSubscriberInterface { private ?LoggerInterface $logger; - public function __construct(LoggerInterface $logger = null) + public function __construct(?LoggerInterface $logger = null) { $this->logger = $logger; } diff --git a/lib/symfony/console/Exception/CommandNotFoundException.php b/lib/symfony/console/Exception/CommandNotFoundException.php index 1e9f1c793..541b32b23 100644 --- a/lib/symfony/console/Exception/CommandNotFoundException.php +++ b/lib/symfony/console/Exception/CommandNotFoundException.php @@ -26,7 +26,7 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce * @param int $code Exception code * @param \Throwable|null $previous Previous exception used for the exception chaining */ - public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null) + public function __construct(string $message, array $alternatives = [], int $code = 0, ?\Throwable $previous = null) { parent::__construct($message, $code, $previous); diff --git a/lib/symfony/console/Formatter/NullOutputFormatterStyle.php b/lib/symfony/console/Formatter/NullOutputFormatterStyle.php index c2ce7d14c..ae23decb1 100644 --- a/lib/symfony/console/Formatter/NullOutputFormatterStyle.php +++ b/lib/symfony/console/Formatter/NullOutputFormatterStyle.php @@ -21,7 +21,7 @@ final class NullOutputFormatterStyle implements OutputFormatterStyleInterface return $text; } - public function setBackground(string $color = null): void + public function setBackground(?string $color = null): void { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -29,7 +29,7 @@ final class NullOutputFormatterStyle implements OutputFormatterStyleInterface // do nothing } - public function setForeground(string $color = null): void + public function setForeground(?string $color = null): void { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); diff --git a/lib/symfony/console/Formatter/OutputFormatterStyle.php b/lib/symfony/console/Formatter/OutputFormatterStyle.php index 346a474c6..21e7f5ab0 100644 --- a/lib/symfony/console/Formatter/OutputFormatterStyle.php +++ b/lib/symfony/console/Formatter/OutputFormatterStyle.php @@ -33,7 +33,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface * @param string|null $foreground The style foreground color name * @param string|null $background The style background color name */ - public function __construct(string $foreground = null, string $background = null, array $options = []) + public function __construct(?string $foreground = null, ?string $background = null, array $options = []) { $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options); } @@ -41,7 +41,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface /** * @return void */ - public function setForeground(string $color = null) + public function setForeground(?string $color = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -52,7 +52,7 @@ class OutputFormatterStyle implements OutputFormatterStyleInterface /** * @return void */ - public function setBackground(string $color = null) + public function setBackground(?string $color = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); diff --git a/lib/symfony/console/Formatter/OutputFormatterStyleStack.php b/lib/symfony/console/Formatter/OutputFormatterStyleStack.php index f98c2eff7..62d2ca0e7 100644 --- a/lib/symfony/console/Formatter/OutputFormatterStyleStack.php +++ b/lib/symfony/console/Formatter/OutputFormatterStyleStack.php @@ -26,7 +26,7 @@ class OutputFormatterStyleStack implements ResetInterface private OutputFormatterStyleInterface $emptyStyle; - public function __construct(OutputFormatterStyleInterface $emptyStyle = null) + public function __construct(?OutputFormatterStyleInterface $emptyStyle = null) { $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle(); $this->reset(); @@ -57,7 +57,7 @@ class OutputFormatterStyleStack implements ResetInterface * * @throws InvalidArgumentException When style tags incorrectly nested */ - public function pop(OutputFormatterStyleInterface $style = null): OutputFormatterStyleInterface + public function pop(?OutputFormatterStyleInterface $style = null): OutputFormatterStyleInterface { if (!$this->styles) { return $this->emptyStyle; diff --git a/lib/symfony/console/Helper/Dumper.php b/lib/symfony/console/Helper/Dumper.php index 8c6a94d51..a3b8e3952 100644 --- a/lib/symfony/console/Helper/Dumper.php +++ b/lib/symfony/console/Helper/Dumper.php @@ -26,7 +26,7 @@ final class Dumper private ?ClonerInterface $cloner; private \Closure $handler; - public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null) + public function __construct(OutputInterface $output, ?CliDumper $dumper = null, ?ClonerInterface $cloner = null) { $this->output = $output; $this->dumper = $dumper; diff --git a/lib/symfony/console/Helper/Helper.php b/lib/symfony/console/Helper/Helper.php index c4b3df72e..5999537d7 100644 --- a/lib/symfony/console/Helper/Helper.php +++ b/lib/symfony/console/Helper/Helper.php @@ -26,7 +26,7 @@ abstract class Helper implements HelperInterface /** * @return void */ - public function setHelperSet(HelperSet $helperSet = null) + public function setHelperSet(?HelperSet $helperSet = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -48,7 +48,9 @@ abstract class Helper implements HelperInterface $string ??= ''; if (preg_match('//u', $string)) { - return (new UnicodeString($string))->width(false); + $string = preg_replace('/[\p{Cc}\x7F]++/u', '', $string, -1, $count); + + return (new UnicodeString($string))->width(false) + $count; } if (false === $encoding = mb_detect_encoding($string, null, true)) { @@ -80,7 +82,7 @@ abstract class Helper implements HelperInterface /** * Returns the subset of a string, using mb_substr if it is available. */ - public static function substr(?string $string, int $from, int $length = null): string + public static function substr(?string $string, int $from, ?int $length = null): string { $string ??= ''; diff --git a/lib/symfony/console/Helper/HelperSet.php b/lib/symfony/console/Helper/HelperSet.php index dc5d499ca..f8c74ca2c 100644 --- a/lib/symfony/console/Helper/HelperSet.php +++ b/lib/symfony/console/Helper/HelperSet.php @@ -38,7 +38,7 @@ class HelperSet implements \IteratorAggregate /** * @return void */ - public function set(HelperInterface $helper, string $alias = null) + public function set(HelperInterface $helper, ?string $alias = null) { $this->helpers[$helper->getName()] = $helper; if (null !== $alias) { diff --git a/lib/symfony/console/Helper/ProcessHelper.php b/lib/symfony/console/Helper/ProcessHelper.php index 26d35a1a8..3ef6f71f7 100644 --- a/lib/symfony/console/Helper/ProcessHelper.php +++ b/lib/symfony/console/Helper/ProcessHelper.php @@ -32,7 +32,7 @@ class ProcessHelper extends Helper * @param callable|null $callback A PHP callback to run whenever there is some * output available on STDOUT or STDERR */ - public function run(OutputInterface $output, array|Process $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process + public function run(OutputInterface $output, array|Process $cmd, ?string $error = null, ?callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE): Process { if (!class_exists(Process::class)) { throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".'); @@ -94,7 +94,7 @@ class ProcessHelper extends Helper * * @see run() */ - public function mustRun(OutputInterface $output, array|Process $cmd, string $error = null, callable $callback = null): Process + public function mustRun(OutputInterface $output, array|Process $cmd, ?string $error = null, ?callable $callback = null): Process { $process = $this->run($output, $cmd, $error, $callback); @@ -108,7 +108,7 @@ class ProcessHelper extends Helper /** * Wraps a Process callback to add debugging output. */ - public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null): callable + public function wrapCallback(OutputInterface $output, Process $process, ?callable $callback = null): callable { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); diff --git a/lib/symfony/console/Helper/ProgressBar.php b/lib/symfony/console/Helper/ProgressBar.php index 64389c4a2..3dc06d7b4 100644 --- a/lib/symfony/console/Helper/ProgressBar.php +++ b/lib/symfony/console/Helper/ProgressBar.php @@ -183,9 +183,9 @@ final class ProgressBar $this->messages[$name] = $message; } - public function getMessage(string $name = 'message'): string + public function getMessage(string $name = 'message'): ?string { - return $this->messages[$name]; + return $this->messages[$name] ?? null; } public function getStartTime(): int @@ -229,7 +229,7 @@ final class ProgressBar public function getRemaining(): float { - if (!$this->step) { + if (0 === $this->step || $this->step === $this->startingStep) { return 0; } @@ -313,7 +313,7 @@ final class ProgressBar * * @return iterable */ - public function iterate(iterable $iterable, int $max = null): iterable + public function iterate(iterable $iterable, ?int $max = null): iterable { $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0)); @@ -332,7 +332,7 @@ final class ProgressBar * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged * @param int $startAt The starting point of the bar (useful e.g. when resuming a previously started bar) */ - public function start(int $max = null, int $startAt = 0): void + public function start(?int $max = null, int $startAt = 0): void { $this->startTime = time(); $this->step = $startAt; @@ -486,12 +486,21 @@ final class ProgressBar if ($this->output instanceof ConsoleSectionOutput) { $messageLines = explode("\n", $this->previousMessage); $lineCount = \count($messageLines); + + $lastLineWithoutDecoration = Helper::removeDecoration($this->output->getFormatter(), end($messageLines) ?? ''); + + // When the last previous line is empty (without formatting) it is already cleared by the section output, so we don't need to clear it again + if ('' === $lastLineWithoutDecoration) { + --$lineCount; + } + foreach ($messageLines as $messageLine) { $messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine)); if ($messageLineLength > $this->terminal->getWidth()) { $lineCount += floor($messageLineLength / $this->terminal->getWidth()); } } + $this->output->clear($lineCount); } else { $lineCount = substr_count($this->previousMessage, "\n"); diff --git a/lib/symfony/console/Helper/ProgressIndicator.php b/lib/symfony/console/Helper/ProgressIndicator.php index 79d47643e..92106caf6 100644 --- a/lib/symfony/console/Helper/ProgressIndicator.php +++ b/lib/symfony/console/Helper/ProgressIndicator.php @@ -50,7 +50,7 @@ class ProgressIndicator * @param int $indicatorChangeInterval Change interval in milliseconds * @param array|null $indicatorValues Animated indicator characters */ - public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null) + public function __construct(OutputInterface $output, ?string $format = null, int $indicatorChangeInterval = 100, ?array $indicatorValues = null) { $this->output = $output; diff --git a/lib/symfony/console/Helper/QuestionHelper.php b/lib/symfony/console/Helper/QuestionHelper.php index f32813c6c..b40b13191 100644 --- a/lib/symfony/console/Helper/QuestionHelper.php +++ b/lib/symfony/console/Helper/QuestionHelper.php @@ -501,19 +501,7 @@ class QuestionHelper extends Helper return self::$stdinIsInteractive; } - if (\function_exists('stream_isatty')) { - return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); - } - - if (\function_exists('posix_isatty')) { - return self::$stdinIsInteractive = @posix_isatty(fopen('php://stdin', 'r')); - } - - if (!\function_exists('shell_exec')) { - return self::$stdinIsInteractive = true; - } - - return self::$stdinIsInteractive = (bool) shell_exec('stty 2> '.('\\' === \DIRECTORY_SEPARATOR ? 'NUL' : '/dev/null')); + return self::$stdinIsInteractive = @stream_isatty(fopen('php://stdin', 'r')); } /** diff --git a/lib/symfony/console/Helper/Table.php b/lib/symfony/console/Helper/Table.php index 3c189580e..0ef771dd4 100644 --- a/lib/symfony/console/Helper/Table.php +++ b/lib/symfony/console/Helper/Table.php @@ -365,13 +365,15 @@ class Table for ($i = 0; $i < $maxRows; ++$i) { $cell = (string) ($row[$i] ?? ''); - $parts = explode("\n", $cell); + $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n"; + $parts = explode($eol, $cell); foreach ($parts as $idx => $part) { if ($headers && !$containsColspan) { if (0 === $idx) { $rows[] = [sprintf( - '%s: %s', - str_pad($headers[$i] ?? '', $maxHeaderLength, ' ', \STR_PAD_LEFT), + '%s%s: %s', + str_repeat(' ', $maxHeaderLength - Helper::width(Helper::removeDecoration($formatter, $headers[$i] ?? ''))), + $headers[$i] ?? '', $part )]; } else { @@ -466,7 +468,7 @@ class Table * * +-----+-----------+-------+ */ - private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null): void + private function renderRowSeparator(int $type = self::SEPARATOR_MID, ?string $title = null, ?string $titleFormat = null): void { if (!$count = $this->numberOfColumns) { return; @@ -531,7 +533,7 @@ class Table * * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | */ - private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null): void + private function renderRow(array $row, string $cellFormat, ?string $firstCellFormat = null): void { $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE); $columns = $this->getRowColumns($row); @@ -562,10 +564,7 @@ class Table } // str_pad won't work properly with multi-byte strings, we need to fix the padding - if (false !== $encoding = mb_detect_encoding($cell, null, true)) { - $width += \strlen($cell) - mb_strwidth($cell, $encoding); - } - + $width += \strlen($cell) - Helper::width($cell) - substr_count($cell, "\0"); $style = $this->getColumnStyle($column); if ($cell instanceof TableSeparator) { @@ -630,15 +629,56 @@ class Table foreach ($rows[$rowKey] as $column => $cell) { $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1; - if (isset($this->columnMaxWidths[$column]) && Helper::width(Helper::removeDecoration($formatter, $cell)) > $this->columnMaxWidths[$column]) { - $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan); + $minWrappedWidth = 0; + $widthApplied = []; + $lengthColumnBorder = $this->getColumnSeparatorWidth() + Helper::width($this->style->getCellRowContentFormat()) - 2; + for ($i = $column; $i < ($column + $colspan); ++$i) { + if (isset($this->columnMaxWidths[$i])) { + $minWrappedWidth += $this->columnMaxWidths[$i]; + $widthApplied[] = ['type' => 'max', 'column' => $i]; + } elseif (($this->columnWidths[$i] ?? 0) > 0 && $colspan > 1) { + $minWrappedWidth += $this->columnWidths[$i]; + $widthApplied[] = ['type' => 'min', 'column' => $i]; + } + } + if (1 === \count($widthApplied)) { + if ($colspan > 1) { + $minWrappedWidth *= $colspan; // previous logic + } + } elseif (\count($widthApplied) > 1) { + $minWrappedWidth += (\count($widthApplied) - 1) * $lengthColumnBorder; + } + + $cellWidth = Helper::width(Helper::removeDecoration($formatter, $cell)); + if ($minWrappedWidth && $cellWidth > $minWrappedWidth) { + $cell = $formatter->formatAndWrap($cell, $minWrappedWidth); + } + // update minimal columnWidths for spanned columns + if ($colspan > 1 && $minWrappedWidth > 0) { + $columnsMinWidthProcessed = []; + $cellWidth = min($cellWidth, $minWrappedWidth); + foreach ($widthApplied as $item) { + if ('max' === $item['type'] && $cellWidth >= $this->columnMaxWidths[$item['column']]) { + $minWidthColumn = $this->columnMaxWidths[$item['column']]; + $this->columnWidths[$item['column']] = $minWidthColumn; + $columnsMinWidthProcessed[$item['column']] = true; + $cellWidth -= $minWidthColumn + $lengthColumnBorder; + } + } + for ($i = $column; $i < ($column + $colspan); ++$i) { + if (isset($columnsMinWidthProcessed[$i])) { + continue; + } + $this->columnWidths[$i] = $cellWidth + $lengthColumnBorder; + } } if (!str_contains($cell ?? '', "\n")) { continue; } - $escaped = implode("\n", array_map(OutputFormatter::escapeTrailingBackslash(...), explode("\n", $cell))); + $eol = str_contains($cell ?? '', "\r\n") ? "\r\n" : "\n"; + $escaped = implode($eol, array_map(OutputFormatter::escapeTrailingBackslash(...), explode($eol, $cell))); $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped; - $lines = explode("\n", str_replace("\n", "\n", $cell)); + $lines = explode($eol, str_replace($eol, ''.$eol, $cell)); foreach ($lines as $lineKey => $line) { if ($colspan > 1) { $line = new TableCell($line, ['colspan' => $colspan]); @@ -700,8 +740,9 @@ class Table $nbLines = $cell->getRowspan() - 1; $lines = [$cell]; if (str_contains($cell, "\n")) { - $lines = explode("\n", str_replace("\n", "\n", $cell)); - $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; + $eol = str_contains($cell, "\r\n") ? "\r\n" : "\n"; + $lines = explode($eol, str_replace($eol, ''.$eol.'', $cell)); + $nbLines = \count($lines) > $nbLines ? substr_count($cell, $eol) : $nbLines; $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]); unset($lines[0]); diff --git a/lib/symfony/console/Helper/TableStyle.php b/lib/symfony/console/Helper/TableStyle.php index bbad98e73..be956c109 100644 --- a/lib/symfony/console/Helper/TableStyle.php +++ b/lib/symfony/console/Helper/TableStyle.php @@ -88,7 +88,7 @@ class TableStyle * * @return $this */ - public function setHorizontalBorderChars(string $outside, string $inside = null): static + public function setHorizontalBorderChars(string $outside, ?string $inside = null): static { $this->horizontalOutsideBorderChar = $outside; $this->horizontalInsideBorderChar = $inside ?? $outside; @@ -113,7 +113,7 @@ class TableStyle * * @return $this */ - public function setVerticalBorderChars(string $outside, string $inside = null): static + public function setVerticalBorderChars(string $outside, ?string $inside = null): static { $this->verticalOutsideBorderChar = $outside; $this->verticalInsideBorderChar = $inside ?? $outside; @@ -167,7 +167,7 @@ class TableStyle * * @return $this */ - public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null): static + public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, ?string $topLeftBottom = null, ?string $topMidBottom = null, ?string $topRightBottom = null): static { $this->crossingChar = $cross; $this->crossingTopLeftChar = $topLeft; diff --git a/lib/symfony/console/Input/ArgvInput.php b/lib/symfony/console/Input/ArgvInput.php index 59f9217ec..ab9f28c54 100644 --- a/lib/symfony/console/Input/ArgvInput.php +++ b/lib/symfony/console/Input/ArgvInput.php @@ -43,7 +43,7 @@ class ArgvInput extends Input private array $tokens; private array $parsed; - public function __construct(array $argv = null, InputDefinition $definition = null) + public function __construct(?array $argv = null, ?InputDefinition $definition = null) { $argv ??= $_SERVER['argv'] ?? []; diff --git a/lib/symfony/console/Input/ArrayInput.php b/lib/symfony/console/Input/ArrayInput.php index 355de61dd..c1bc914ca 100644 --- a/lib/symfony/console/Input/ArrayInput.php +++ b/lib/symfony/console/Input/ArrayInput.php @@ -27,7 +27,7 @@ class ArrayInput extends Input { private array $parameters; - public function __construct(array $parameters, InputDefinition $definition = null) + public function __construct(array $parameters, ?InputDefinition $definition = null) { $this->parameters = $parameters; diff --git a/lib/symfony/console/Input/Input.php b/lib/symfony/console/Input/Input.php index c7959a6ce..1c21573bc 100644 --- a/lib/symfony/console/Input/Input.php +++ b/lib/symfony/console/Input/Input.php @@ -34,7 +34,7 @@ abstract class Input implements InputInterface, StreamableInputInterface protected $arguments = []; protected $interactive = true; - public function __construct(InputDefinition $definition = null) + public function __construct(?InputDefinition $definition = null) { if (null === $definition) { $this->definition = new InputDefinition(); diff --git a/lib/symfony/console/Input/InputArgument.php b/lib/symfony/console/Input/InputArgument.php index 5cb151488..4ef79feb7 100644 --- a/lib/symfony/console/Input/InputArgument.php +++ b/lib/symfony/console/Input/InputArgument.php @@ -44,7 +44,7 @@ class InputArgument * * @throws InvalidArgumentException When argument mode is not valid */ - public function __construct(string $name, int $mode = null, string $description = '', string|bool|int|float|array $default = null, \Closure|array $suggestedValues = []) + public function __construct(string $name, ?int $mode = null, string $description = '', string|bool|int|float|array|null $default = null, \Closure|array $suggestedValues = []) { if (null === $mode) { $mode = self::OPTIONAL; @@ -95,7 +95,7 @@ class InputArgument * * @throws LogicException When incorrect default value is given */ - public function setDefault(string|bool|int|float|array $default = null) + public function setDefault(string|bool|int|float|array|null $default = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); diff --git a/lib/symfony/console/Input/InputOption.php b/lib/symfony/console/Input/InputOption.php index fdf88dcc2..bb533801f 100644 --- a/lib/symfony/console/Input/InputOption.php +++ b/lib/symfony/console/Input/InputOption.php @@ -65,7 +65,7 @@ class InputOption * * @throws InvalidArgumentException If option mode is invalid or incompatible */ - public function __construct(string $name, string|array $shortcut = null, int $mode = null, string $description = '', string|bool|int|float|array $default = null, array|\Closure $suggestedValues = []) + public function __construct(string $name, string|array|null $shortcut = null, ?int $mode = null, string $description = '', string|bool|int|float|array|null $default = null, array|\Closure $suggestedValues = []) { if (str_starts_with($name, '--')) { $name = substr($name, 2); @@ -75,7 +75,7 @@ class InputOption throw new InvalidArgumentException('An option name cannot be empty.'); } - if (empty($shortcut)) { + if ('' === $shortcut || [] === $shortcut || false === $shortcut) { $shortcut = null; } @@ -84,10 +84,10 @@ class InputOption $shortcut = implode('|', $shortcut); } $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); - $shortcuts = array_filter($shortcuts); + $shortcuts = array_filter($shortcuts, 'strlen'); $shortcut = implode('|', $shortcuts); - if (empty($shortcut)) { + if ('' === $shortcut) { throw new InvalidArgumentException('An option shortcut cannot be empty.'); } } @@ -181,7 +181,7 @@ class InputOption /** * @return void */ - public function setDefault(string|bool|int|float|array $default = null) + public function setDefault(string|bool|int|float|array|null $default = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); diff --git a/lib/symfony/console/Output/ConsoleOutput.php b/lib/symfony/console/Output/ConsoleOutput.php index c1eb7cd14..5837e74a3 100644 --- a/lib/symfony/console/Output/ConsoleOutput.php +++ b/lib/symfony/console/Output/ConsoleOutput.php @@ -37,7 +37,7 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) */ - public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null) + public function __construct(int $verbosity = self::VERBOSITY_NORMAL, ?bool $decorated = null, ?OutputFormatterInterface $formatter = null) { parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); diff --git a/lib/symfony/console/Output/ConsoleSectionOutput.php b/lib/symfony/console/Output/ConsoleSectionOutput.php index 21c4a44a8..f2d7933bb 100644 --- a/lib/symfony/console/Output/ConsoleSectionOutput.php +++ b/lib/symfony/console/Output/ConsoleSectionOutput.php @@ -63,7 +63,7 @@ class ConsoleSectionOutput extends StreamOutput * * @return void */ - public function clear(int $lines = null) + public function clear(?int $lines = null) { if (empty($this->content) || !$this->isDecorated()) { return; diff --git a/lib/symfony/console/Output/Output.php b/lib/symfony/console/Output/Output.php index 3a06311a8..00f481e03 100644 --- a/lib/symfony/console/Output/Output.php +++ b/lib/symfony/console/Output/Output.php @@ -37,7 +37,7 @@ abstract class Output implements OutputInterface * @param bool $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) */ - public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) + public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, ?OutputFormatterInterface $formatter = null) { $this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL; $this->formatter = $formatter ?? new OutputFormatter(); diff --git a/lib/symfony/console/Output/StreamOutput.php b/lib/symfony/console/Output/StreamOutput.php index 08005c292..f51d03763 100644 --- a/lib/symfony/console/Output/StreamOutput.php +++ b/lib/symfony/console/Output/StreamOutput.php @@ -40,7 +40,7 @@ class StreamOutput extends Output * * @throws InvalidArgumentException When first argument is not a real stream */ - public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null) + public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, ?bool $decorated = null, ?OutputFormatterInterface $formatter = null) { if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); @@ -93,21 +93,33 @@ class StreamOutput extends Output protected function hasColorSupport(): bool { // Follow https://no-color.org/ - if (isset($_SERVER['NO_COLOR']) || false !== getenv('NO_COLOR')) { + if ('' !== (($_SERVER['NO_COLOR'] ?? getenv('NO_COLOR'))[0] ?? '')) { return false; } - if (\DIRECTORY_SEPARATOR === '\\' - && \function_exists('sapi_windows_vt100_support') - && @sapi_windows_vt100_support($this->stream) + // Detect msysgit/mingw and assume this is a tty because detection + // does not work correctly, see https://github.com/composer/composer/issues/9690 + if (!@stream_isatty($this->stream) && !\in_array(strtoupper((string) getenv('MSYSTEM')), ['MINGW32', 'MINGW64'], true)) { + return false; + } + + if ('\\' === \DIRECTORY_SEPARATOR && @sapi_windows_vt100_support($this->stream)) { + return true; + } + + if ('Hyper' === getenv('TERM_PROGRAM') + || false !== getenv('COLORTERM') + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') ) { return true; } - return 'Hyper' === getenv('TERM_PROGRAM') - || false !== getenv('ANSICON') - || 'ON' === getenv('ConEmuANSI') - || str_starts_with((string) getenv('TERM'), 'xterm') - || stream_isatty($this->stream); + if ('dumb' === $term = (string) getenv('TERM')) { + return false; + } + + // See https://github.com/chalk/supports-color/blob/d4f413efaf8da045c5ab440ed418ef02dbb28bf1/index.js#L157 + return preg_match('/^((screen|xterm|vt100|vt220|putty|rxvt|ansi|cygwin|linux).*)|(.*-256(color)?(-bce)?)$/', $term); } } diff --git a/lib/symfony/console/Output/TrimmedBufferOutput.php b/lib/symfony/console/Output/TrimmedBufferOutput.php index b00445ece..23a2be8c3 100644 --- a/lib/symfony/console/Output/TrimmedBufferOutput.php +++ b/lib/symfony/console/Output/TrimmedBufferOutput.php @@ -24,7 +24,7 @@ class TrimmedBufferOutput extends Output private int $maxLength; private string $buffer = ''; - public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, OutputFormatterInterface $formatter = null) + public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = false, ?OutputFormatterInterface $formatter = null) { if ($maxLength <= 0) { throw new InvalidArgumentException(sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength)); diff --git a/lib/symfony/console/Question/ChoiceQuestion.php b/lib/symfony/console/Question/ChoiceQuestion.php index e449ff683..465f3184f 100644 --- a/lib/symfony/console/Question/ChoiceQuestion.php +++ b/lib/symfony/console/Question/ChoiceQuestion.php @@ -26,11 +26,11 @@ class ChoiceQuestion extends Question private string $errorMessage = 'Value "%s" is invalid'; /** - * @param string $question The question to ask to the user - * @param array $choices The list of available choices - * @param mixed $default The default answer to return + * @param string $question The question to ask to the user + * @param array $choices The list of available choices + * @param string|bool|int|float|null $default The default answer to return */ - public function __construct(string $question, array $choices, mixed $default = null) + public function __construct(string $question, array $choices, string|bool|int|float|null $default = null) { if (!$choices) { throw new \LogicException('Choice question must have at least 1 choice available.'); diff --git a/lib/symfony/console/Question/Question.php b/lib/symfony/console/Question/Question.php index 26896bb53..94c688fa8 100644 --- a/lib/symfony/console/Question/Question.php +++ b/lib/symfony/console/Question/Question.php @@ -36,7 +36,7 @@ class Question * @param string $question The question to ask to the user * @param string|bool|int|float|null $default The default answer to return if the user enters nothing */ - public function __construct(string $question, string|bool|int|float $default = null) + public function __construct(string $question, string|bool|int|float|null $default = null) { $this->question = $question; $this->default = $default; @@ -175,7 +175,7 @@ class Question * * @return $this */ - public function setAutocompleterCallback(callable $callback = null): static + public function setAutocompleterCallback(?callable $callback = null): static { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -194,7 +194,7 @@ class Question * * @return $this */ - public function setValidator(callable $validator = null): static + public function setValidator(?callable $validator = null): static { if (1 > \func_num_args()) { trigger_deprecation('symfony/console', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); diff --git a/lib/symfony/console/Resources/completion.bash b/lib/symfony/console/Resources/completion.bash index 0d76eacc3..64c6a338f 100644 --- a/lib/symfony/console/Resources/completion.bash +++ b/lib/symfony/console/Resources/completion.bash @@ -17,7 +17,7 @@ _sf_{{ COMMAND_NAME }}() { done # Use newline as only separator to allow space in completion values - IFS=$'\n' + local IFS=$'\n' local sf_cmd="${COMP_WORDS[0]}" # for an alias, get the real script behind it diff --git a/lib/symfony/console/SignalRegistry/SignalMap.php b/lib/symfony/console/SignalRegistry/SignalMap.php index de419bda7..2f9aa67c1 100644 --- a/lib/symfony/console/SignalRegistry/SignalMap.php +++ b/lib/symfony/console/SignalRegistry/SignalMap.php @@ -27,7 +27,7 @@ class SignalMap if (!isset(self::$map)) { $r = new \ReflectionExtension('pcntl'); $c = $r->getConstants(); - $map = array_filter($c, fn ($k) => str_starts_with($k, 'SIG') && !str_starts_with($k, 'SIG_'), \ARRAY_FILTER_USE_KEY); + $map = array_filter($c, fn ($k) => str_starts_with($k, 'SIG') && !str_starts_with($k, 'SIG_') && 'SIGBABY' !== $k, \ARRAY_FILTER_USE_KEY); self::$map = array_flip($map); } diff --git a/lib/symfony/console/SingleCommandApplication.php b/lib/symfony/console/SingleCommandApplication.php index 4f0b5ba3c..ff1c17247 100644 --- a/lib/symfony/console/SingleCommandApplication.php +++ b/lib/symfony/console/SingleCommandApplication.php @@ -46,7 +46,7 @@ class SingleCommandApplication extends Command return $this; } - public function run(InputInterface $input = null, OutputInterface $output = null): int + public function run(?InputInterface $input = null, ?OutputInterface $output = null): int { if ($this->running) { return parent::run($input, $output); diff --git a/lib/symfony/console/Style/StyleInterface.php b/lib/symfony/console/Style/StyleInterface.php index e25a65bd2..6bced158a 100644 --- a/lib/symfony/console/Style/StyleInterface.php +++ b/lib/symfony/console/Style/StyleInterface.php @@ -91,12 +91,12 @@ interface StyleInterface /** * Asks a question. */ - public function ask(string $question, string $default = null, callable $validator = null): mixed; + public function ask(string $question, ?string $default = null, ?callable $validator = null): mixed; /** * Asks a question with the user input hidden. */ - public function askHidden(string $question, callable $validator = null): mixed; + public function askHidden(string $question, ?callable $validator = null): mixed; /** * Asks for confirmation. diff --git a/lib/symfony/console/Style/SymfonyStyle.php b/lib/symfony/console/Style/SymfonyStyle.php index 43d2edf5a..03bda8784 100644 --- a/lib/symfony/console/Style/SymfonyStyle.php +++ b/lib/symfony/console/Style/SymfonyStyle.php @@ -63,7 +63,7 @@ class SymfonyStyle extends OutputStyle * * @return void */ - public function block(string|array $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) + public function block(string|array $messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = true) { $messages = \is_array($messages) ? array_values($messages) : [$messages]; @@ -249,7 +249,7 @@ class SymfonyStyle extends OutputStyle $this->horizontalTable($headers, [$row]); } - public function ask(string $question, string $default = null, callable $validator = null): mixed + public function ask(string $question, ?string $default = null, ?callable $validator = null): mixed { $question = new Question($question, $default); $question->setValidator($validator); @@ -257,7 +257,7 @@ class SymfonyStyle extends OutputStyle return $this->askQuestion($question); } - public function askHidden(string $question, callable $validator = null): mixed + public function askHidden(string $question, ?callable $validator = null): mixed { $question = new Question($question); @@ -336,7 +336,7 @@ class SymfonyStyle extends OutputStyle * * @return iterable */ - public function progressIterate(iterable $iterable, int $max = null): iterable + public function progressIterate(iterable $iterable, ?int $max = null): iterable { yield from $this->createProgressBar()->iterate($iterable, $max); @@ -456,7 +456,7 @@ class SymfonyStyle extends OutputStyle $this->bufferedOutput->write($message, $newLine, $type); } - private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array + private function createBlock(iterable $messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false): array { $indentLength = 0; $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix)); diff --git a/lib/symfony/console/Terminal.php b/lib/symfony/console/Terminal.php index 3eda0376b..f094adedc 100644 --- a/lib/symfony/console/Terminal.php +++ b/lib/symfony/console/Terminal.php @@ -217,8 +217,7 @@ class Terminal $cp = \function_exists('sapi_windows_cp_set') ? sapi_windows_cp_get() : 0; - $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); - if (!\is_resource($process)) { + if (!$process = @proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true])) { return null; } diff --git a/lib/symfony/css-selector/Node/ElementNode.php b/lib/symfony/css-selector/Node/ElementNode.php index 39f4d9cc0..76d2078ea 100644 --- a/lib/symfony/css-selector/Node/ElementNode.php +++ b/lib/symfony/css-selector/Node/ElementNode.php @@ -26,7 +26,7 @@ class ElementNode extends AbstractNode private ?string $namespace; private ?string $element; - public function __construct(string $namespace = null, string $element = null) + public function __construct(?string $namespace = null, ?string $element = null) { $this->namespace = $namespace; $this->element = $element; diff --git a/lib/symfony/css-selector/Node/SelectorNode.php b/lib/symfony/css-selector/Node/SelectorNode.php index 0b09ab5dc..2318b2bf2 100644 --- a/lib/symfony/css-selector/Node/SelectorNode.php +++ b/lib/symfony/css-selector/Node/SelectorNode.php @@ -26,7 +26,7 @@ class SelectorNode extends AbstractNode private NodeInterface $tree; private ?string $pseudoElement; - public function __construct(NodeInterface $tree, string $pseudoElement = null) + public function __construct(NodeInterface $tree, ?string $pseudoElement = null) { $this->tree = $tree; $this->pseudoElement = $pseudoElement ? strtolower($pseudoElement) : null; diff --git a/lib/symfony/css-selector/Parser/Parser.php b/lib/symfony/css-selector/Parser/Parser.php index 5313d3435..309c9b521 100644 --- a/lib/symfony/css-selector/Parser/Parser.php +++ b/lib/symfony/css-selector/Parser/Parser.php @@ -29,7 +29,7 @@ class Parser implements ParserInterface { private Tokenizer $tokenizer; - public function __construct(Tokenizer $tokenizer = null) + public function __construct(?Tokenizer $tokenizer = null) { $this->tokenizer = $tokenizer ?? new Tokenizer(); } diff --git a/lib/symfony/css-selector/XPath/Translator.php b/lib/symfony/css-selector/XPath/Translator.php index 83e855b5c..9e66ce7dd 100644 --- a/lib/symfony/css-selector/XPath/Translator.php +++ b/lib/symfony/css-selector/XPath/Translator.php @@ -48,7 +48,7 @@ class Translator implements TranslatorInterface private array $pseudoClassTranslators = []; private array $attributeMatchingTranslators = []; - public function __construct(ParserInterface $parser = null) + public function __construct(?ParserInterface $parser = null) { $this->mainParser = $parser ?? new Parser(); diff --git a/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php b/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php index 44023876f..69ee83d18 100644 --- a/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php +++ b/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php @@ -31,7 +31,7 @@ class ServerDumpPlaceholderCommand extends Command { private ServerDumpCommand $replacedCommand; - public function __construct(DumpServer $server = null, array $descriptors = []) + public function __construct(?DumpServer $server = null, array $descriptors = []) { $this->replacedCommand = new ServerDumpCommand((new \ReflectionClass(DumpServer::class))->newInstanceWithoutConstructor(), $descriptors); diff --git a/lib/symfony/debug-bundle/DebugBundle.php b/lib/symfony/debug-bundle/DebugBundle.php index 9782bf8e3..0af84fb5a 100644 --- a/lib/symfony/debug-bundle/DebugBundle.php +++ b/lib/symfony/debug-bundle/DebugBundle.php @@ -35,10 +35,10 @@ class DebugBundle extends Bundle // The dump data collector is used by default, so dump output is sent to // the WDT. In a CLI context, if dump is used too soon, the data collector // will buffer it, and release it at the end of the script. - VarDumper::setHandler(function ($var, string $label = null) use ($container) { + VarDumper::setHandler(function ($var, ?string $label = null) use ($container) { $dumper = $container->get('data_collector.dump'); $cloner = $container->get('var_dumper.cloner'); - $handler = function ($var, string $label = null) use ($dumper, $cloner) { + $handler = function ($var, ?string $label = null) use ($dumper, $cloner) { $var = $cloner->cloneVar($var); if (null !== $label) { $var = $var->withContext(['label' => $label]); diff --git a/lib/symfony/dependency-injection/Argument/BoundArgument.php b/lib/symfony/dependency-injection/Argument/BoundArgument.php index be24e20af..22d94140a 100644 --- a/lib/symfony/dependency-injection/Argument/BoundArgument.php +++ b/lib/symfony/dependency-injection/Argument/BoundArgument.php @@ -28,7 +28,7 @@ final class BoundArgument implements ArgumentInterface private int $type; private ?string $file; - public function __construct(mixed $value, bool $trackUsage = true, int $type = 0, string $file = null) + public function __construct(mixed $value, bool $trackUsage = true, int $type = 0, ?string $file = null) { $this->value = $value; if ($trackUsage) { diff --git a/lib/symfony/dependency-injection/Argument/LazyClosure.php b/lib/symfony/dependency-injection/Argument/LazyClosure.php index 230363a95..45e1c9d56 100644 --- a/lib/symfony/dependency-injection/Argument/LazyClosure.php +++ b/lib/symfony/dependency-injection/Argument/LazyClosure.php @@ -40,22 +40,22 @@ class LazyClosure } if (isset($this->initializer)) { - $this->service = ($this->initializer)(); + if (\is_string($service = ($this->initializer)())) { + $service = (new \ReflectionClass($service))->newInstanceWithoutConstructor(); + } + $this->service = $service; unset($this->initializer); } return $this->service; } - public static function getCode(string $initializer, array $callable, Definition $definition, ContainerBuilder $container, ?string $id): string + public static function getCode(string $initializer, array $callable, string $class, ContainerBuilder $container, ?string $id): string { $method = $callable[1]; - $asClosure = 'Closure' === ($definition->getClass() ?: 'Closure'); - if ($asClosure) { + if ($asClosure = 'Closure' === $class) { $class = ($callable[0] instanceof Reference ? $container->findDefinition($callable[0]) : $callable[0])->getClass(); - } else { - $class = $definition->getClass(); } $r = $container->getReflectionClass($class); diff --git a/lib/symfony/dependency-injection/Argument/ServiceLocator.php b/lib/symfony/dependency-injection/Argument/ServiceLocator.php index e58293489..8276f6a39 100644 --- a/lib/symfony/dependency-injection/Argument/ServiceLocator.php +++ b/lib/symfony/dependency-injection/Argument/ServiceLocator.php @@ -24,7 +24,7 @@ class ServiceLocator extends BaseServiceLocator private array $serviceMap; private ?array $serviceTypes; - public function __construct(\Closure $factory, array $serviceMap, array $serviceTypes = null) + public function __construct(\Closure $factory, array $serviceMap, ?array $serviceTypes = null) { $this->factory = $factory; $this->serviceMap = $serviceMap; diff --git a/lib/symfony/dependency-injection/Argument/TaggedIteratorArgument.php b/lib/symfony/dependency-injection/Argument/TaggedIteratorArgument.php index b4e982c45..bba5e34ae 100644 --- a/lib/symfony/dependency-injection/Argument/TaggedIteratorArgument.php +++ b/lib/symfony/dependency-injection/Argument/TaggedIteratorArgument.php @@ -35,7 +35,7 @@ class TaggedIteratorArgument extends IteratorArgument * @param array $exclude Services to exclude from the iterator * @param bool $excludeSelf Whether to automatically exclude the referencing service from the iterator */ - public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false, string $defaultPriorityMethod = null, array $exclude = [], bool $excludeSelf = true) + public function __construct(string $tag, ?string $indexAttribute = null, ?string $defaultIndexMethod = null, bool $needsIndexes = false, ?string $defaultPriorityMethod = null, array $exclude = [], bool $excludeSelf = true) { parent::__construct([]); diff --git a/lib/symfony/dependency-injection/Attribute/AutoconfigureTag.php b/lib/symfony/dependency-injection/Attribute/AutoconfigureTag.php index ed5807ca0..a83a6e975 100644 --- a/lib/symfony/dependency-injection/Attribute/AutoconfigureTag.php +++ b/lib/symfony/dependency-injection/Attribute/AutoconfigureTag.php @@ -19,7 +19,7 @@ namespace Symfony\Component\DependencyInjection\Attribute; #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)] class AutoconfigureTag extends Autoconfigure { - public function __construct(string $name = null, array $attributes = []) + public function __construct(?string $name = null, array $attributes = []) { parent::__construct( tags: [ diff --git a/lib/symfony/dependency-injection/Attribute/Autowire.php b/lib/symfony/dependency-injection/Attribute/Autowire.php index c17eb1370..874092657 100644 --- a/lib/symfony/dependency-injection/Attribute/Autowire.php +++ b/lib/symfony/dependency-injection/Attribute/Autowire.php @@ -38,11 +38,11 @@ class Autowire * @param bool|class-string|class-string[] $lazy Whether to use lazy-loading for this argument */ public function __construct( - string|array|ArgumentInterface $value = null, - string $service = null, - string $expression = null, - string $env = null, - string $param = null, + string|array|ArgumentInterface|null $value = null, + ?string $service = null, + ?string $expression = null, + ?string $env = null, + ?string $param = null, bool|string|array $lazy = false, ) { if ($this->lazy = \is_string($lazy) ? [$lazy] : $lazy) { diff --git a/lib/symfony/dependency-injection/Attribute/AutowireCallable.php b/lib/symfony/dependency-injection/Attribute/AutowireCallable.php index 87e119746..da9ac0d00 100644 --- a/lib/symfony/dependency-injection/Attribute/AutowireCallable.php +++ b/lib/symfony/dependency-injection/Attribute/AutowireCallable.php @@ -25,9 +25,9 @@ class AutowireCallable extends Autowire * @param bool|class-string $lazy Whether to use lazy-loading for this argument */ public function __construct( - string|array $callable = null, - string $service = null, - string $method = null, + string|array|null $callable = null, + ?string $service = null, + ?string $method = null, bool|string $lazy = false, ) { if (!(null !== $callable xor null !== $service)) { @@ -42,7 +42,7 @@ class AutowireCallable extends Autowire public function buildDefinition(mixed $value, ?string $type, \ReflectionParameter $parameter): Definition { - return (new Definition($type = \is_string($this->lazy) ? $this->lazy : ($type ?: 'Closure'))) + return (new Definition($type = \is_array($this->lazy) ? current($this->lazy) : ($type ?: 'Closure'))) ->setFactory(['Closure', 'fromCallable']) ->setArguments([\is_array($value) ? $value + [1 => '__invoke'] : $value]) ->setLazy($this->lazy || 'Closure' !== $type && 'callable' !== (string) $parameter->getType()); diff --git a/lib/symfony/dependency-injection/Attribute/AutowireIterator.php b/lib/symfony/dependency-injection/Attribute/AutowireIterator.php index b81bd8f92..1c4d2a3df 100644 --- a/lib/symfony/dependency-injection/Attribute/AutowireIterator.php +++ b/lib/symfony/dependency-injection/Attribute/AutowireIterator.php @@ -24,9 +24,9 @@ class AutowireIterator extends Autowire */ public function __construct( string $tag, - string $indexAttribute = null, - string $defaultIndexMethod = null, - string $defaultPriorityMethod = null, + ?string $indexAttribute = null, + ?string $defaultIndexMethod = null, + ?string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = true, ) { diff --git a/lib/symfony/dependency-injection/Attribute/AutowireLocator.php b/lib/symfony/dependency-injection/Attribute/AutowireLocator.php index a60a76960..5d3cf374f 100644 --- a/lib/symfony/dependency-injection/Attribute/AutowireLocator.php +++ b/lib/symfony/dependency-injection/Attribute/AutowireLocator.php @@ -28,14 +28,14 @@ class AutowireLocator extends Autowire /** * @see ServiceSubscriberInterface::getSubscribedServices() * - * @param string|array $services An explicit list of services or a tag name - * @param string|string[] $exclude A service or a list of services to exclude + * @param string|array $services An explicit list of services or a tag name + * @param string|string[] $exclude A service or a list of services to exclude */ public function __construct( string|array $services, - string $indexAttribute = null, - string $defaultIndexMethod = null, - string $defaultPriorityMethod = null, + ?string $indexAttribute = null, + ?string $defaultIndexMethod = null, + ?string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = true, ) { diff --git a/lib/symfony/dependency-injection/Attribute/Target.php b/lib/symfony/dependency-injection/Attribute/Target.php index 6fbb3ad42..028be557d 100644 --- a/lib/symfony/dependency-injection/Attribute/Target.php +++ b/lib/symfony/dependency-injection/Attribute/Target.php @@ -36,7 +36,7 @@ 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 &$parsedName = 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) { diff --git a/lib/symfony/dependency-injection/Compiler/AbstractRecursivePass.php b/lib/symfony/dependency-injection/Compiler/AbstractRecursivePass.php index f18baa57c..fd395be76 100644 --- a/lib/symfony/dependency-injection/Compiler/AbstractRecursivePass.php +++ b/lib/symfony/dependency-injection/Compiler/AbstractRecursivePass.php @@ -82,7 +82,7 @@ abstract class AbstractRecursivePass implements CompilerPassInterface continue; } if ($isRoot) { - if ($v->hasTag('container.excluded')) { + if ($v instanceof Definition && $v->hasTag('container.excluded')) { continue; } $this->currentId = $k; @@ -219,6 +219,10 @@ abstract class AbstractRecursivePass implements CompilerPassInterface return new \ReflectionMethod(static function (...$arguments) {}, '__invoke'); } + if ($r->hasMethod('__callStatic') && ($r = $r->getMethod('__callStatic')) && $r->isPublic()) { + return new \ReflectionMethod(static function (...$arguments) {}, '__invoke'); + } + throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); } diff --git a/lib/symfony/dependency-injection/Compiler/AutowirePass.php b/lib/symfony/dependency-injection/Compiler/AutowirePass.php index 9786ec4de..d622c335b 100644 --- a/lib/symfony/dependency-injection/Compiler/AutowirePass.php +++ b/lib/symfony/dependency-injection/Compiler/AutowirePass.php @@ -696,7 +696,7 @@ class AutowirePass extends AbstractRecursivePass return null; } - private function populateAutowiringAlias(string $id, string $target = null): void + private function populateAutowiringAlias(string $id, ?string $target = null): void { if (!preg_match('/(?(DEFINE)(?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/', $id, $m)) { return; @@ -716,7 +716,7 @@ class AutowirePass extends AbstractRecursivePass } } - private function getCombinedAlias(string $type, string $name = null): ?string + private function getCombinedAlias(string $type, ?string $name = null): ?string { if (str_contains($type, '&')) { $types = explode('&', $type); diff --git a/lib/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php b/lib/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php index 1fb8935c3..a4a8ce368 100644 --- a/lib/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php +++ b/lib/symfony/dependency-injection/Compiler/CheckCircularReferencesPass.php @@ -28,6 +28,7 @@ class CheckCircularReferencesPass implements CompilerPassInterface { private array $currentPath; private array $checkedNodes; + private array $checkedLazyNodes; /** * Checks the ContainerBuilder object for circular references. @@ -59,22 +60,36 @@ class CheckCircularReferencesPass implements CompilerPassInterface $node = $edge->getDestNode(); $id = $node->getId(); - if (empty($this->checkedNodes[$id])) { - // Don't check circular references for lazy edges - if (!$node->getValue() || (!$edge->isLazy() && !$edge->isWeak())) { - $searchKey = array_search($id, $this->currentPath); - $this->currentPath[] = $id; + if (!empty($this->checkedNodes[$id])) { + continue; + } - if (false !== $searchKey) { - throw new ServiceCircularReferenceException($id, \array_slice($this->currentPath, $searchKey)); - } + $isLeaf = !!$node->getValue(); + $isConcrete = !$edge->isLazy() && !$edge->isWeak(); - $this->checkOutEdges($node->getOutEdges()); + // Skip already checked lazy services if they are still lazy. Will not gain any new information. + if (!empty($this->checkedLazyNodes[$id]) && (!$isLeaf || !$isConcrete)) { + continue; + } + + // Process concrete references, otherwise defer check circular references for lazy edges. + if (!$isLeaf || $isConcrete) { + $searchKey = array_search($id, $this->currentPath); + $this->currentPath[] = $id; + + if (false !== $searchKey) { + throw new ServiceCircularReferenceException($id, \array_slice($this->currentPath, $searchKey)); } + $this->checkOutEdges($node->getOutEdges()); + $this->checkedNodes[$id] = true; - array_pop($this->currentPath); + unset($this->checkedLazyNodes[$id]); + } else { + $this->checkedLazyNodes[$id] = true; } + + array_pop($this->currentPath); } } } diff --git a/lib/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/lib/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php index 7a6dd7687..bbf318982 100644 --- a/lib/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php +++ b/lib/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php @@ -60,15 +60,7 @@ class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass if (isset($this->serviceLocatorContextIds[$currentId])) { $currentId = $this->serviceLocatorContextIds[$currentId]; $locator = $this->container->getDefinition($this->currentId)->getFactory()[0]; - - foreach ($locator->getArgument(0) as $k => $v) { - if ($v->getValues()[0] === $value) { - if ($k !== $id) { - $currentId = $k.'" in the container provided to "'.$currentId; - } - throw new ServiceNotFoundException($id, $currentId, null, $this->getAlternatives($id)); - } - } + $this->throwServiceNotFoundException($value, $currentId, $locator->getArgument(0)); } if ('.' === $currentId[0] && $graph->hasNode($currentId)) { @@ -82,14 +74,21 @@ class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass $currentId = $sourceId; break; } + + if (isset($this->serviceLocatorContextIds[$sourceId])) { + $currentId = $this->serviceLocatorContextIds[$sourceId]; + $locator = $this->container->getDefinition($this->currentId); + $this->throwServiceNotFoundException($value, $currentId, $locator->getArgument(0)); + } } } - throw new ServiceNotFoundException($id, $currentId, null, $this->getAlternatives($id)); + $this->throwServiceNotFoundException($value, $currentId, $value); } - private function getAlternatives(string $id): array + private function throwServiceNotFoundException(Reference $ref, string $sourceId, $value): void { + $id = (string) $ref; $alternatives = []; foreach ($this->container->getServiceIds() as $knownId) { if ('' === $knownId || '.' === $knownId[0] || $knownId === $this->currentId) { @@ -102,6 +101,28 @@ class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass } } - return $alternatives; + $pass = new class() extends AbstractRecursivePass { + public Reference $ref; + public string $sourceId; + public array $alternatives; + + public function processValue(mixed $value, bool $isRoot = false): mixed + { + if ($this->ref !== $value) { + return parent::processValue($value, $isRoot); + } + $sourceId = $this->sourceId; + if (null !== $this->currentId && $this->currentId !== (string) $value) { + $sourceId = $this->currentId.'" in the container provided to "'.$sourceId; + } + + throw new ServiceNotFoundException((string) $value, $sourceId, null, $this->alternatives); + } + }; + $pass->ref = $ref; + $pass->sourceId = $sourceId; + $pass->alternatives = $alternatives; + + $pass->processValue($value, true); } } diff --git a/lib/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php b/lib/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php index 4830bad1a..074d89990 100644 --- a/lib/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php +++ b/lib/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php @@ -163,7 +163,7 @@ final class CheckTypeDeclarationsPass extends AbstractRecursivePass /** * @throws InvalidParameterTypeException When a parameter is not compatible with the declared type */ - private function checkType(Definition $checkedDefinition, mixed $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix, \ReflectionType $reflectionType = null): void + private function checkType(Definition $checkedDefinition, mixed $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix, ?\ReflectionType $reflectionType = null): void { $reflectionType ??= $parameter->getType(); diff --git a/lib/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php b/lib/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php index b6a2cf907..204401cd2 100644 --- a/lib/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php +++ b/lib/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php @@ -65,7 +65,10 @@ class DefinitionErrorExceptionPass extends AbstractRecursivePass } if ($value instanceof Reference && $this->currentId !== $targetId = (string) $value) { - if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { + if ( + ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() + || ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior() + ) { $this->sourceReferences[$targetId][$this->currentId] ??= true; } else { $this->sourceReferences[$targetId][$this->currentId] = false; diff --git a/lib/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php b/lib/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php index 57e14b77b..c87ee3e79 100644 --- a/lib/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php +++ b/lib/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php @@ -34,7 +34,7 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass private array $notInlinableIds = []; private ?ServiceReferenceGraph $graph = null; - public function __construct(AnalyzeServiceReferencesPass $analyzingPass = null) + public function __construct(?AnalyzeServiceReferencesPass $analyzingPass = null) { $this->analyzingPass = $analyzingPass; } @@ -73,6 +73,9 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass if (!$this->graph->hasNode($id)) { continue; } + if ($definition->isPublic()) { + $this->connectedIds[$id] = true; + } foreach ($this->graph->getNode($id)->getOutEdges() as $edge) { if (isset($notInlinedIds[$edge->getSourceNode()->getId()])) { $this->currentId = $id; @@ -189,17 +192,13 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass return true; } - if ($definition->isPublic()) { + if ($definition->isPublic() + || $this->currentId === $id + || !$this->graph->hasNode($id) + ) { return false; } - if (!$this->graph->hasNode($id)) { - return true; - } - - if ($this->currentId === $id) { - return false; - } $this->connectedIds[$id] = true; $srcIds = []; @@ -224,6 +223,8 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass return false; } - return $this->container->getDefinition($srcId)->isShared(); + $srcDefinition = $this->container->getDefinition($srcId); + + return $srcDefinition->isShared() && !$srcDefinition->isLazy(); } } diff --git a/lib/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php b/lib/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php index cd8ebfe0f..b7a44445a 100644 --- a/lib/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php +++ b/lib/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php @@ -156,7 +156,7 @@ class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder { private string $extensionClass; - public function __construct(ExtensionInterface $extension, ParameterBagInterface $parameterBag = null) + public function __construct(ExtensionInterface $extension, ?ParameterBagInterface $parameterBag = null) { parent::__construct($parameterBag); @@ -178,7 +178,7 @@ class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass)); } - public function resolveEnvPlaceholders(mixed $value, string|bool $format = null, array &$usedEnvs = null): mixed + public function resolveEnvPlaceholders(mixed $value, string|bool|null $format = null, ?array &$usedEnvs = null): mixed { if (true !== $format || !\is_string($value)) { return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); diff --git a/lib/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php b/lib/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php index 701786245..5d2110bf9 100644 --- a/lib/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php +++ b/lib/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php @@ -85,7 +85,8 @@ trait PriorityTaggedServiceTrait } elseif (null === $defaultIndex && $defaultPriorityMethod && $class) { $defaultIndex = PriorityTaggedServiceUtil::getDefault($container, $serviceId, $class, $defaultIndexMethod ?? 'getDefaultName', $tagName, $indexAttribute, $checkTaggedItem); } - $index ??= $defaultIndex ??= $serviceId; + $decorated = $definition->getTag('container.decorator')[0]['id'] ?? null; + $index = $index ?? $defaultIndex ?? $defaultIndex = $decorated ?? $serviceId; $services[] = [$priority, ++$i, $index, $serviceId, $class]; } @@ -133,6 +134,10 @@ class PriorityTaggedServiceUtil return null; } + if ($r->isInterface()) { + return null; + } + if (null !== $indexAttribute) { $service = $class !== $serviceId ? sprintf('service "%s"', $serviceId) : 'on the corresponding service'; $message = [sprintf('Either method "%s::%s()" should ', $class, $defaultMethod), sprintf(' or tag "%s" on %s is missing attribute "%s".', $tagName, $service, $indexAttribute)]; diff --git a/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php b/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php index 2fa7db848..f041d1771 100644 --- a/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php +++ b/lib/symfony/dependency-injection/Compiler/ResolveBindingsPass.php @@ -11,9 +11,11 @@ namespace Symfony\Component\DependencyInjection\Compiler; +use Symfony\Component\DependencyInjection\Argument\AbstractArgument; use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\DependencyInjection\Attribute\Target; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; @@ -181,10 +183,17 @@ class ResolveBindingsPass extends AbstractRecursivePass foreach ($reflectionMethod->getParameters() as $key => $parameter) { $names[$key] = $parameter->name; - if (\array_key_exists($key, $arguments) && '' !== $arguments[$key]) { + if (\array_key_exists($key, $arguments) && '' !== $arguments[$key] && !$arguments[$key] instanceof AbstractArgument) { continue; } - if (\array_key_exists($parameter->name, $arguments) && '' !== $arguments[$parameter->name]) { + if (\array_key_exists($parameter->name, $arguments) && '' !== $arguments[$parameter->name] && !$arguments[$parameter->name] instanceof AbstractArgument) { + continue; + } + if ( + $value->isAutowired() + && !$value->hasTag('container.ignore_attributes') + && $parameter->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF) + ) { continue; } @@ -222,7 +231,9 @@ class ResolveBindingsPass extends AbstractRecursivePass foreach ($names as $key => $name) { if (\array_key_exists($name, $arguments) && (0 === $key || \array_key_exists($key - 1, $arguments))) { - $arguments[$key] = $arguments[$name]; + if (!array_key_exists($key, $arguments)) { + $arguments[$key] = $arguments[$name]; + } unset($arguments[$name]); } } diff --git a/lib/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php b/lib/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php index fb0fc2682..845482119 100644 --- a/lib/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php +++ b/lib/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php @@ -102,7 +102,7 @@ final class ServiceLocatorTagPass extends AbstractRecursivePass return new Reference($id); } - public static function register(ContainerBuilder $container, array $map, string $callerId = null): Reference + public static function register(ContainerBuilder $container, array $map, ?string $callerId = null): Reference { foreach ($map as $k => $v) { $map[$k] = new ServiceClosureArgument($v); diff --git a/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php b/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php index c90fc7ac5..8310fb241 100644 --- a/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php +++ b/lib/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php @@ -74,7 +74,7 @@ class ServiceReferenceGraph /** * Connects 2 nodes together in the Graph. */ - public function connect(?string $sourceId, mixed $sourceValue, ?string $destId, mixed $destValue = null, Reference $reference = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false): void + public function connect(?string $sourceId, mixed $sourceValue, ?string $destId, mixed $destValue = null, ?Reference $reference = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false): void { if (null === $sourceId || null === $destId) { return; diff --git a/lib/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php b/lib/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php index 2d6542660..75bd6097d 100644 --- a/lib/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php +++ b/lib/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php @@ -49,17 +49,8 @@ class ValidateEnvPlaceholdersPass implements CompilerPassInterface $defaultBag = new ParameterBag($resolvingBag->all()); $envTypes = $resolvingBag->getProvidedTypes(); foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) { - $values = []; - if (false === $i = strpos($env, ':')) { - $default = $defaultBag->has("env($env)") ? $defaultBag->get("env($env)") : self::TYPE_FIXTURES['string']; - $defaultType = null !== $default ? get_debug_type($default) : 'string'; - $values[$defaultType] = $default; - } else { - $prefix = substr($env, 0, $i); - foreach ($envTypes[$prefix] ?? ['string'] as $type) { - $values[$type] = self::TYPE_FIXTURES[$type] ?? null; - } - } + $values = $this->getPlaceholderValues($env, $defaultBag, $envTypes); + foreach ($placeholders as $placeholder) { BaseNode::setPlaceholder($placeholder, $values); } @@ -100,4 +91,50 @@ class ValidateEnvPlaceholdersPass implements CompilerPassInterface $this->extensionConfig = []; } } + + /** + * @param array> $envTypes + * + * @return array + */ + private function getPlaceholderValues(string $env, ParameterBag $defaultBag, array $envTypes): array + { + if (false === $i = strpos($env, ':')) { + [$default, $defaultType] = $this->getParameterDefaultAndDefaultType("env($env)", $defaultBag); + + return [$defaultType => $default]; + } + + $prefix = substr($env, 0, $i); + if ('default' === $prefix) { + $parts = explode(':', $env); + array_shift($parts); // Remove 'default' prefix + $parameter = array_shift($parts); // Retrieve and remove parameter + + [$defaultParameter, $defaultParameterType] = $this->getParameterDefaultAndDefaultType($parameter, $defaultBag); + + return [ + $defaultParameterType => $defaultParameter, + ...$this->getPlaceholderValues(implode(':', $parts), $defaultBag, $envTypes), + ]; + } + + $values = []; + foreach ($envTypes[$prefix] ?? ['string'] as $type) { + $values[$type] = self::TYPE_FIXTURES[$type] ?? null; + } + + return $values; + } + + /** + * @return array{0: string, 1: string} + */ + private function getParameterDefaultAndDefaultType(string $name, ParameterBag $defaultBag): array + { + $default = $defaultBag->has($name) ? $defaultBag->get($name) : self::TYPE_FIXTURES['string']; + $defaultType = null !== $default ? get_debug_type($default) : 'string'; + + return [$default, $defaultType]; + } } diff --git a/lib/symfony/dependency-injection/Container.php b/lib/symfony/dependency-injection/Container.php index 0777a8755..f21028edb 100644 --- a/lib/symfony/dependency-injection/Container.php +++ b/lib/symfony/dependency-injection/Container.php @@ -67,7 +67,7 @@ class Container implements ContainerInterface, ResetInterface private static \Closure $make; - public function __construct(ParameterBagInterface $parameterBag = null) + public function __construct(?ParameterBagInterface $parameterBag = null) { $this->parameterBag = $parameterBag ?? new EnvPlaceholderParameterBag(); } @@ -288,7 +288,6 @@ class Container implements ContainerInterface, ResetInterface public function reset() { $services = $this->services + $this->privates; - $this->services = $this->factories = $this->privates = []; foreach ($services as $service) { try { @@ -299,6 +298,8 @@ class Container implements ContainerInterface, ResetInterface continue; } } + + $this->services = $this->factories = $this->privates = []; } /** diff --git a/lib/symfony/dependency-injection/ContainerAwareTrait.php b/lib/symfony/dependency-injection/ContainerAwareTrait.php index be6b225a3..d716a580d 100644 --- a/lib/symfony/dependency-injection/ContainerAwareTrait.php +++ b/lib/symfony/dependency-injection/ContainerAwareTrait.php @@ -30,7 +30,7 @@ trait ContainerAwareTrait /** * @return void */ - public function setContainer(ContainerInterface $container = null) + public function setContainer(?ContainerInterface $container = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/dependency-injection', '6.2', 'Calling "%s::%s()" without any arguments is deprecated, pass null explicitly instead.', __CLASS__, __FUNCTION__); diff --git a/lib/symfony/dependency-injection/ContainerBuilder.php b/lib/symfony/dependency-injection/ContainerBuilder.php index f56072a35..4dc7c4e23 100644 --- a/lib/symfony/dependency-injection/ContainerBuilder.php +++ b/lib/symfony/dependency-injection/ContainerBuilder.php @@ -117,7 +117,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface private array $vendors; /** - * @var string[] the list of paths in vendor directories + * @var array the cache for paths being in vendor directories */ private array $pathsInVendor = []; @@ -155,7 +155,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface 'mixed' => true, ]; - public function __construct(ParameterBagInterface $parameterBag = null) + public function __construct(?ParameterBagInterface $parameterBag = null) { parent::__construct($parameterBag); @@ -360,7 +360,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface $resource = new ClassExistenceResource($class, false); $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); } else { - $classReflector = class_exists($class) ? new \ReflectionClass($class) : false; + $classReflector = class_exists($class) || interface_exists($class, false) ? new \ReflectionClass($class) : false; } } catch (\ReflectionException $e) { if ($throw) { @@ -431,7 +431,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface * @throws BadMethodCallException When this ContainerBuilder is compiled * @throws \LogicException if the extension is not registered */ - public function loadFromExtension(string $extension, array $values = null): static + public function loadFromExtension(string $extension, ?array $values = null): static { if ($this->isCompiled()) { throw new BadMethodCallException('Cannot load from an extension on a compiled container.'); @@ -531,7 +531,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface return $this->doGet($id, $invalidBehavior); } - private function doGet(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, bool $isConstructorArgument = false): mixed + private function doGet(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, ?array &$inlineServices = null, bool $isConstructorArgument = false): mixed { if (isset($inlineServices[$id])) { return $inlineServices[$id]; @@ -742,10 +742,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface * * The parameter bag is frozen; * * Extension loading is disabled. * - * @param bool $resolveEnvPlaceholders Whether %env()% parameters should be resolved using the current - * env vars or be replaced by uniquely identifiable placeholders. - * Set to "true" when you want to use the current ContainerBuilder - * directly, keep to "false" when the container is dumped instead. + * @param bool $resolveEnvPlaceholders Whether %env()% parameters should be resolved at build time using + * the current env var values (true), or be resolved at runtime based + * on the environment (false). In general, this should be set to "true" + * when you want to use the current ContainerBuilder directly, and to + * "false" when the container is dumped instead. * * @return void */ @@ -900,7 +901,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface * This methods allows for simple registration of service definition * with a fluid interface. */ - public function register(string $id, string $class = null): Definition + public function register(string $id, ?string $class = null): Definition { return $this->setDefinition($id, new Definition($class)); } @@ -911,7 +912,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface * This method implements a shortcut for using setDefinition() with * an autowired definition. */ - public function autowire(string $id, string $class = null): Definition + public function autowire(string $id, ?string $class = null): Definition { return $this->setDefinition($id, (new Definition($class))->setAutowired(true)); } @@ -1029,7 +1030,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface * @throws RuntimeException When the service is a synthetic service * @throws InvalidArgumentException When configure callable is not callable */ - private function createService(Definition $definition, array &$inlineServices, bool $isConstructorArgument = false, string $id = null, bool|object $tryProxy = true): mixed + private function createService(Definition $definition, array &$inlineServices, bool $isConstructorArgument = false, ?string $id = null, bool|object $tryProxy = true): mixed { if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) { return $inlineServices[$h]; @@ -1059,14 +1060,15 @@ class ContainerBuilder extends Container implements TaggedContainerInterface } if (\is_array($callable) && ( - $callable[0] instanceof Reference + 'Closure' !== $class + || $callable[0] instanceof Reference || $callable[0] instanceof Definition && !isset($inlineServices[spl_object_hash($callable[0])]) )) { $initializer = function () use ($callable, &$inlineServices) { return $this->doResolveServices($callable[0], $inlineServices); }; - $proxy = eval('return '.LazyClosure::getCode('$initializer', $callable, $definition, $this, $id).';'); + $proxy = eval('return '.LazyClosure::getCode('$initializer', $callable, $class, $this, $id).';'); $this->shareService($definition, $proxy, $id, $inlineServices); return $proxy; @@ -1380,7 +1382,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface * "$fooBar"-named arguments with $type as type-hint. Such arguments will * receive the service $id when autowiring is used. */ - public function registerAliasForArgument(string $id, string $type, string $name = null): Alias + public function registerAliasForArgument(string $id, string $type, ?string $name = null): Alias { $parsedName = (new Target($name ??= $id))->getParsedName(); @@ -1427,7 +1429,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface * * @return mixed The value with env parameters resolved if a string or an array is passed */ - public function resolveEnvPlaceholders(mixed $value, string|bool $format = null, array &$usedEnvs = null): mixed + public function resolveEnvPlaceholders(mixed $value, string|bool|null $format = null, ?array &$usedEnvs = null): mixed { $bag = $this->getParameterBag(); if (true === $format ??= '%%env(%s)%%') { diff --git a/lib/symfony/dependency-injection/Definition.php b/lib/symfony/dependency-injection/Definition.php index 71e6258a8..68da10e62 100644 --- a/lib/symfony/dependency-injection/Definition.php +++ b/lib/symfony/dependency-injection/Definition.php @@ -61,7 +61,7 @@ class Definition */ public ?int $decorationOnInvalid = null; - public function __construct(string $class = null, array $arguments = []) + public function __construct(?string $class = null, array $arguments = []) { if (null !== $class) { $this->setClass($class); @@ -133,7 +133,7 @@ class Definition * * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals */ - public function setDecoratedService(?string $id, string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): static + public function setDecoratedService(?string $id, ?string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): static { if ($renamedId && $id === $renamedId) { throw new InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id)); @@ -180,8 +180,6 @@ class Definition /** * Gets the service class. - * - * @return class-string|null */ public function getClass(): ?string { diff --git a/lib/symfony/dependency-injection/Dumper/PhpDumper.php b/lib/symfony/dependency-injection/Dumper/PhpDumper.php index 65985fd9c..164dddf20 100644 --- a/lib/symfony/dependency-injection/Dumper/PhpDumper.php +++ b/lib/symfony/dependency-injection/Dumper/PhpDumper.php @@ -353,7 +353,7 @@ $preloadedFiles EOF; foreach ($this->preload as $class) { - if (!$class || str_contains($class, '$') || \in_array($class, ['int', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void'], true)) { + if (!$class || str_contains($class, '$') || \in_array($class, ['int', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void', 'never'], true)) { continue; } if (!(class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) || (new \ReflectionClass($class))->isUserDefined()) { @@ -624,7 +624,9 @@ EOF; $proxyCode = substr(self::stripComments($proxyCode), 5); } - $proxyClass = explode(' ', $this->inlineRequires ? substr($proxyCode, \strlen($code)) : $proxyCode, 3)[1]; + $proxyClass = $this->inlineRequires ? substr($proxyCode, \strlen($code)) : $proxyCode; + $i = strpos($proxyClass, 'class'); + $proxyClass = substr($proxyClass, 6 + $i, strpos($proxyClass, ' ', 7 + $i) - $i - 6); if ($this->asFiles || $this->namespace) { $proxyCode .= "\nif (!\\class_exists('$proxyClass', false)) {\n \\class_alias(__NAMESPACE__.'\\\\$proxyClass', '$proxyClass', false);\n}\n"; @@ -844,8 +846,7 @@ EOF; if ($class = $definition->getClass()) { $class = $class instanceof Parameter ? '%'.$class.'%' : $this->container->resolveEnvPlaceholders($class); $return[] = sprintf(str_starts_with($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\')); - } elseif ($definition->getFactory()) { - $factory = $definition->getFactory(); + } elseif ($factory = $definition->getFactory()) { if (\is_string($factory) && !str_starts_with($factory, '@=')) { $return[] = sprintf('@return object An instance returned by %s()', $factory); } elseif (\is_array($factory) && (\is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) { @@ -1048,7 +1049,7 @@ EOTXT return $code; } - private function addInlineService(string $id, Definition $definition, Definition $inlineDef = null, bool $forConstructor = true): string + private function addInlineService(string $id, Definition $definition, ?Definition $inlineDef = null, bool $forConstructor = true): string { $code = ''; @@ -1108,7 +1109,7 @@ EOTXT return $code."\n return \$instance;\n"; } - private function addServices(array &$services = null): string + private function addServices(?array &$services = null): string { $publicServices = $privateServices = ''; $definitions = $this->container->getDefinitions(); @@ -1150,7 +1151,7 @@ EOTXT } } - private function addNewInstance(Definition $definition, string $return = '', string $id = null, bool $asGhostObject = false): string + private function addNewInstance(Definition $definition, string $return = '', ?string $id = null, bool $asGhostObject = false): string { $tail = $return ? str_repeat(')', substr_count($return, '(') - substr_count($return, ')')).";\n" : ''; @@ -1168,9 +1169,7 @@ EOTXT $arguments[] = (\is_string($i) ? $i.': ' : '').$this->dumpValue($value); } - if (null !== $definition->getFactory()) { - $callable = $definition->getFactory(); - + if ($callable = $definition->getFactory()) { if ('current' === $callable && [0] === array_keys($definition->getArguments()) && \is_array($value) && [0] === array_keys($value)) { return $return.$this->dumpValue($value[0]).$tail; } @@ -1203,13 +1202,13 @@ EOTXT throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s).', $callable[1] ?: 'n/a')); } - if (['...'] === $arguments && ($definition->isLazy() || 'Closure' !== ($definition->getClass() ?? 'Closure')) && ( + if (['...'] === $arguments && ('Closure' !== ($class = $definition->getClass() ?: 'Closure') || $definition->isLazy() && ( $callable[0] instanceof Reference || ($callable[0] instanceof Definition && !$this->definitionVariables->contains($callable[0])) - )) { + ))) { $initializer = 'fn () => '.$this->dumpValue($callable[0]); - return $return.LazyClosure::getCode($initializer, $callable, $definition, $this->container, $id).$tail; + return $return.LazyClosure::getCode($initializer, $callable, $class, $this->container, $id).$tail; } if ($callable[0] instanceof Reference @@ -1779,7 +1778,7 @@ EOF; return implode(' && ', $conditions); } - private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage $definitions = null, array &$calls = [], bool $byConstructor = null): \SplObjectStorage + private function getDefinitionsFromArguments(array $arguments, ?\SplObjectStorage $definitions = null, array &$calls = [], ?bool $byConstructor = null): \SplObjectStorage { $definitions ??= new \SplObjectStorage(); @@ -2010,7 +2009,7 @@ EOF; return sprintf('$container->parameters[%s]', $this->doExport($name)); } - private function getServiceCall(string $id, Reference $reference = null): string + private function getServiceCall(string $id, ?Reference $reference = null): string { while ($this->container->hasAlias($id)) { $id = (string) $this->container->getAlias($id); @@ -2183,6 +2182,12 @@ EOF; if ($edge->isLazy() || !$value instanceof Definition || !$value->isShared()) { return false; } + + // When the source node is a proxy or ghost, it will construct its references only when the node itself is initialized. + // Since the node can be cloned before being fully initialized, we do not know how often its references are used. + if ($this->getProxyDumper()->isProxyCandidate($value)) { + return false; + } $ids[$edge->getSourceNode()->getId()] = true; } @@ -2291,7 +2296,6 @@ EOF; private function getClasses(Definition $definition, string $id): array { $classes = []; - $resolve = $this->container->getParameterBag()->resolveValue(...); while ($definition instanceof Definition) { foreach ($definition->getTag($this->preloadTags[0]) as $tag) { @@ -2303,24 +2307,24 @@ EOF; } if ($class = $definition->getClass()) { - $classes[] = trim($resolve($class), '\\'); + $classes[] = trim($class, '\\'); } $factory = $definition->getFactory(); - if (!\is_array($factory)) { - $factory = [$factory]; + if (\is_string($factory) && !str_starts_with($factory, '@=') && str_contains($factory, '::')) { + $factory = explode('::', $factory); } - if (\is_string($factory[0])) { - $factory[0] = $resolve($factory[0]); + if (!\is_array($factory)) { + $definition = $factory; + continue; + } - if (false !== $i = strrpos($factory[0], '::')) { - $factory[0] = substr($factory[0], 0, $i); - } + $definition = $factory[0] ?? null; + + if (\is_string($definition)) { $classes[] = trim($factory[0], '\\'); } - - $definition = $factory[0]; } return $classes; diff --git a/lib/symfony/dependency-injection/Dumper/XmlDumper.php b/lib/symfony/dependency-injection/Dumper/XmlDumper.php index 05d424d15..6ae8d5c61 100644 --- a/lib/symfony/dependency-injection/Dumper/XmlDumper.php +++ b/lib/symfony/dependency-injection/Dumper/XmlDumper.php @@ -134,16 +134,17 @@ class XmlDumper extends Dumper foreach ($tags as $name => $tags) { foreach ($tags as $attributes) { $tag = $this->document->createElement('tag'); - if (!\array_key_exists('name', $attributes)) { - $tag->setAttribute('name', $name); - } else { - $tag->appendChild($this->document->createTextNode($name)); - } // Check if we have recursive attributes if (array_filter($attributes, \is_array(...))) { + $tag->setAttribute('name', $name); $this->addTagRecursiveAttributes($tag, $attributes); } else { + if (!\array_key_exists('name', $attributes)) { + $tag->setAttribute('name', $name); + } else { + $tag->appendChild($this->document->createTextNode($name)); + } foreach ($attributes as $key => $value) { $tag->setAttribute($key, $value ?? ''); } diff --git a/lib/symfony/dependency-injection/Dumper/YamlDumper.php b/lib/symfony/dependency-injection/Dumper/YamlDumper.php index 5c96e3b32..299558039 100644 --- a/lib/symfony/dependency-injection/Dumper/YamlDumper.php +++ b/lib/symfony/dependency-injection/Dumper/YamlDumper.php @@ -50,18 +50,18 @@ class YamlDumper extends Dumper $this->dumper ??= new YmlDumper(); - return $this->container->resolveEnvPlaceholders($this->addParameters()."\n".$this->addServices()); + return $this->addParameters()."\n".$this->addServices(); } private function addService(string $id, Definition $definition): string { - $code = " $id:\n"; + $code = " {$this->dumper->dump($id)}:\n"; if ($class = $definition->getClass()) { if (str_starts_with($class, '\\')) { $class = substr($class, 1); } - $code .= sprintf(" class: %s\n", $this->dumper->dump($class)); + $code .= sprintf(" class: %s\n", $this->dumper->dump($this->container->resolveEnvPlaceholders($class))); } if (!$definition->isPrivate()) { @@ -87,7 +87,7 @@ class YamlDumper extends Dumper } if ($definition->getFile()) { - $code .= sprintf(" file: %s\n", $this->dumper->dump($definition->getFile())); + $code .= sprintf(" file: %s\n", $this->dumper->dump($this->container->resolveEnvPlaceholders($definition->getFile()))); } if ($definition->isSynthetic()) { @@ -238,7 +238,7 @@ class YamlDumper extends Dumper } } - return $callable; + return $this->container->resolveEnvPlaceholders($callable); } /** @@ -299,7 +299,7 @@ class YamlDumper extends Dumper if (\is_array($value)) { $code = []; foreach ($value as $k => $v) { - $code[$k] = $this->dumpValue($v); + $code[$this->container->resolveEnvPlaceholders($k)] = $this->dumpValue($v); } return $code; @@ -319,10 +319,10 @@ class YamlDumper extends Dumper throw new RuntimeException(sprintf('Unable to dump a service container if a parameter is an object or a resource, got "%s".', get_debug_type($value))); } - return $value; + return $this->container->resolveEnvPlaceholders($value); } - private function getServiceCall(string $id, Reference $reference = null): string + private function getServiceCall(string $id, ?Reference $reference = null): string { if (null !== $reference) { switch ($reference->getInvalidBehavior()) { @@ -359,7 +359,7 @@ class YamlDumper extends Dumper $filtered[$key] = $value; } - return $escape ? $this->escape($filtered) : $filtered; + return $escape ? $this->container->resolveEnvPlaceholders($this->escape($filtered)) : $filtered; } private function escape(array $arguments): array diff --git a/lib/symfony/dependency-injection/EnvVarLoaderInterface.php b/lib/symfony/dependency-injection/EnvVarLoaderInterface.php index 0c547f8a5..803156be2 100644 --- a/lib/symfony/dependency-injection/EnvVarLoaderInterface.php +++ b/lib/symfony/dependency-injection/EnvVarLoaderInterface.php @@ -19,7 +19,7 @@ namespace Symfony\Component\DependencyInjection; interface EnvVarLoaderInterface { /** - * @return string[] Key/value pairs that can be accessed using the regular "%env()%" syntax + * @return array Key/value pairs that can be accessed using the regular "%env()%" syntax */ public function loadEnvVars(): array; } diff --git a/lib/symfony/dependency-injection/EnvVarProcessor.php b/lib/symfony/dependency-injection/EnvVarProcessor.php index bae5e289d..4ab93b6df 100644 --- a/lib/symfony/dependency-injection/EnvVarProcessor.php +++ b/lib/symfony/dependency-injection/EnvVarProcessor.php @@ -28,7 +28,7 @@ class EnvVarProcessor implements EnvVarProcessorInterface /** * @param \Traversable|null $loaders */ - public function __construct(ContainerInterface $container, \Traversable $loaders = null) + public function __construct(ContainerInterface $container, ?\Traversable $loaders = null) { $this->container = $container; $this->loaders = $loaders ?? new \ArrayIterator(); @@ -164,10 +164,16 @@ class EnvVarProcessor implements EnvVarProcessorInterface if (false !== $i || 'string' !== $prefix) { $env = $getEnv($name); } elseif ('' === ($env = $_ENV[$name] ?? (str_starts_with($name, 'HTTP_') ? null : ($_SERVER[$name] ?? null))) - || (false !== $env && false === ($env = $env ?? getenv($name) ?? false)) // null is a possible value because of thread safety issues + || (false !== $env && false === $env ??= getenv($name) ?? false) // null is a possible value because of thread safety issues ) { - foreach ($this->loadedVars as $vars) { - if (false !== ($env = ($vars[$name] ?? $env)) && '' !== $env) { + foreach ($this->loadedVars as $i => $vars) { + if (false === $env = $vars[$name] ?? $env) { + continue; + } + if ($env instanceof \Stringable) { + $this->loadedVars[$i][$name] = $env = (string) $env; + } + if ('' !== ($env ?? '')) { break; } } @@ -185,7 +191,13 @@ class EnvVarProcessor implements EnvVarProcessorInterface continue; } $this->loadedVars[] = $vars = $loader->loadEnvVars(); - if (false !== ($env = ($vars[$name] ?? $env)) && '' !== $env) { + if (false === $env = $vars[$name] ?? $env) { + continue; + } + if ($env instanceof \Stringable) { + $this->loadedVars[array_key_last($this->loadedVars)][$name] = $env = (string) $env; + } + if ('' !== ($env ?? '')) { $ended = false; break; } @@ -286,15 +298,15 @@ class EnvVarProcessor implements EnvVarProcessorInterface } if ('url' === $prefix) { - $parsedEnv = parse_url($env); + $params = parse_url($env); - if (false === $parsedEnv) { + if (false === $params) { throw new RuntimeException(sprintf('Invalid URL in env var "%s".', $name)); } - if (!isset($parsedEnv['scheme'], $parsedEnv['host'])) { - throw new RuntimeException(sprintf('Invalid URL env var "%s": schema and host expected, "%s" given.', $name, $env)); + if (!isset($params['scheme'], $params['host'])) { + throw new RuntimeException(sprintf('Invalid URL in env var "%s": scheme and host expected.', $name)); } - $parsedEnv += [ + $params += [ 'port' => null, 'user' => null, 'pass' => null, @@ -303,10 +315,13 @@ class EnvVarProcessor implements EnvVarProcessorInterface 'fragment' => null, ]; - // remove the '/' separator - $parsedEnv['path'] = '/' === ($parsedEnv['path'] ?? '/') ? '' : substr($parsedEnv['path'], 1); + $params['user'] = null !== $params['user'] ? rawurldecode($params['user']) : null; + $params['pass'] = null !== $params['pass'] ? rawurldecode($params['pass']) : null; - return $parsedEnv; + // remove the '/' separator + $params['path'] = '/' === ($params['path'] ?? '/') ? '' : substr($params['path'], 1); + + return $params; } if ('query_string' === $prefix) { diff --git a/lib/symfony/dependency-injection/Exception/AutowiringFailedException.php b/lib/symfony/dependency-injection/Exception/AutowiringFailedException.php index 5f22fa53b..872e2609b 100644 --- a/lib/symfony/dependency-injection/Exception/AutowiringFailedException.php +++ b/lib/symfony/dependency-injection/Exception/AutowiringFailedException.php @@ -19,13 +19,11 @@ class AutowiringFailedException extends RuntimeException private string $serviceId; private ?\Closure $messageCallback = null; - public function __construct(string $serviceId, string|\Closure $message = '', int $code = 0, \Throwable $previous = null) + public function __construct(string $serviceId, string|\Closure $message = '', int $code = 0, ?\Throwable $previous = null) { $this->serviceId = $serviceId; - if ($message instanceof \Closure - && (\function_exists('xdebug_is_enabled') ? xdebug_is_enabled() : \function_exists('xdebug_info')) - ) { + if ($message instanceof \Closure && \function_exists('xdebug_is_enabled') && xdebug_is_enabled()) { $message = $message(); } diff --git a/lib/symfony/dependency-injection/Exception/EnvParameterException.php b/lib/symfony/dependency-injection/Exception/EnvParameterException.php index 48b5e486a..6cd53c9f7 100644 --- a/lib/symfony/dependency-injection/Exception/EnvParameterException.php +++ b/lib/symfony/dependency-injection/Exception/EnvParameterException.php @@ -18,7 +18,7 @@ namespace Symfony\Component\DependencyInjection\Exception; */ class EnvParameterException extends InvalidArgumentException { - public function __construct(array $envs, \Throwable $previous = null, string $message = 'Incompatible use of dynamic environment variables "%s" found in parameters.') + public function __construct(array $envs, ?\Throwable $previous = null, string $message = 'Incompatible use of dynamic environment variables "%s" found in parameters.') { parent::__construct(sprintf($message, implode('", "', $envs)), 0, $previous); } diff --git a/lib/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php b/lib/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php index 9fc3b50b6..325377d12 100644 --- a/lib/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php +++ b/lib/symfony/dependency-injection/Exception/ParameterCircularReferenceException.php @@ -20,7 +20,7 @@ class ParameterCircularReferenceException extends RuntimeException { private array $parameters; - public function __construct(array $parameters, \Throwable $previous = null) + public function __construct(array $parameters, ?\Throwable $previous = null) { parent::__construct(sprintf('Circular reference detected for parameter "%s" ("%s" > "%s").', $parameters[0], implode('" > "', $parameters), $parameters[0]), 0, $previous); diff --git a/lib/symfony/dependency-injection/Exception/ParameterNotFoundException.php b/lib/symfony/dependency-injection/Exception/ParameterNotFoundException.php index 69f7b3a50..61c9357b9 100644 --- a/lib/symfony/dependency-injection/Exception/ParameterNotFoundException.php +++ b/lib/symfony/dependency-injection/Exception/ParameterNotFoundException.php @@ -34,7 +34,7 @@ class ParameterNotFoundException extends InvalidArgumentException implements Not * @param string[] $alternatives Some parameter name alternatives * @param string|null $nonNestedAlternative The alternative parameter name when the user expected dot notation for nested parameters */ - public function __construct(string $key, string $sourceId = null, string $sourceKey = null, \Throwable $previous = null, array $alternatives = [], string $nonNestedAlternative = null) + public function __construct(string $key, ?string $sourceId = null, ?string $sourceKey = null, ?\Throwable $previous = null, array $alternatives = [], ?string $nonNestedAlternative = null) { $this->key = $key; $this->sourceId = $sourceId; diff --git a/lib/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php b/lib/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php index d62c22567..85b7f5731 100644 --- a/lib/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php +++ b/lib/symfony/dependency-injection/Exception/ServiceCircularReferenceException.php @@ -21,7 +21,7 @@ class ServiceCircularReferenceException extends RuntimeException private string $serviceId; private array $path; - public function __construct(string $serviceId, array $path, \Throwable $previous = null) + public function __construct(string $serviceId, array $path, ?\Throwable $previous = null) { parent::__construct(sprintf('Circular reference detected for service "%s", path: "%s".', $serviceId, implode(' -> ', $path)), 0, $previous); diff --git a/lib/symfony/dependency-injection/Exception/ServiceNotFoundException.php b/lib/symfony/dependency-injection/Exception/ServiceNotFoundException.php index d56db7727..68dc6ee43 100644 --- a/lib/symfony/dependency-injection/Exception/ServiceNotFoundException.php +++ b/lib/symfony/dependency-injection/Exception/ServiceNotFoundException.php @@ -24,7 +24,7 @@ class ServiceNotFoundException extends InvalidArgumentException implements NotFo private ?string $sourceId; private array $alternatives; - public function __construct(string $id, string $sourceId = null, \Throwable $previous = null, array $alternatives = [], string $msg = null) + public function __construct(string $id, ?string $sourceId = null, ?\Throwable $previous = null, array $alternatives = [], ?string $msg = null) { if (null !== $msg) { // no-op diff --git a/lib/symfony/dependency-injection/ExpressionLanguage.php b/lib/symfony/dependency-injection/ExpressionLanguage.php index 1a7f5fd38..84d45dbdd 100644 --- a/lib/symfony/dependency-injection/ExpressionLanguage.php +++ b/lib/symfony/dependency-injection/ExpressionLanguage.php @@ -27,7 +27,7 @@ if (!class_exists(BaseExpressionLanguage::class)) { */ class ExpressionLanguage extends BaseExpressionLanguage { - public function __construct(CacheItemPoolInterface $cache = null, array $providers = [], callable $serviceCompiler = null, \Closure $getEnv = null) + public function __construct(?CacheItemPoolInterface $cache = null, array $providers = [], ?callable $serviceCompiler = null, ?\Closure $getEnv = null) { // prepend the default provider to let users override it easily array_unshift($providers, new ExpressionLanguageProvider($serviceCompiler, $getEnv)); diff --git a/lib/symfony/dependency-injection/ExpressionLanguageProvider.php b/lib/symfony/dependency-injection/ExpressionLanguageProvider.php index d0cc1f70b..60479ea37 100644 --- a/lib/symfony/dependency-injection/ExpressionLanguageProvider.php +++ b/lib/symfony/dependency-injection/ExpressionLanguageProvider.php @@ -30,7 +30,7 @@ class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface private ?\Closure $getEnv; - public function __construct(callable $serviceCompiler = null, \Closure $getEnv = null) + public function __construct(?callable $serviceCompiler = null, ?\Closure $getEnv = null) { $this->serviceCompiler = null === $serviceCompiler ? null : $serviceCompiler(...); $this->getEnv = $getEnv; @@ -45,7 +45,7 @@ class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface new ExpressionFunction('env', fn ($arg) => sprintf('$container->getEnv(%s)', $arg), function (array $variables, $value) { if (!$this->getEnv) { - throw new LogicException('You need to pass a getEnv closure to the expression langage provider to use the "env" function.'); + throw new LogicException('You need to pass a getEnv closure to the expression language provider to use the "env" function.'); } return ($this->getEnv)($value); diff --git a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php b/lib/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php index 520977763..b8f31ee41 100644 --- a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php +++ b/lib/symfony/dependency-injection/LazyProxy/PhpDumper/DumperInterface.php @@ -26,7 +26,7 @@ interface DumperInterface * @param bool|null &$asGhostObject Set to true after the call if the proxy is a ghost object * @param string|null $id */ - public function isProxyCandidate(Definition $definition/* , bool &$asGhostObject = null, string $id = null */): bool; + public function isProxyCandidate(Definition $definition/* , ?bool &$asGhostObject = null, ?string $id = null */): bool; /** * Generates the code to be used to instantiate a proxy in the dumped factory code. @@ -38,5 +38,5 @@ interface DumperInterface * * @param string|null $id */ - public function getProxyCode(Definition $definition/* , string $id = null */): string; + public function getProxyCode(Definition $definition/* , ?string $id = null */): string; } diff --git a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php b/lib/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php index 2571fccbf..0d4426c44 100644 --- a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php +++ b/lib/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php @@ -26,7 +26,7 @@ final class LazyServiceDumper implements DumperInterface ) { } - public function isProxyCandidate(Definition $definition, bool &$asGhostObject = null, string $id = null): bool + public function isProxyCandidate(Definition $definition, ?bool &$asGhostObject = null, ?string $id = null): bool { $asGhostObject = false; @@ -96,7 +96,7 @@ final class LazyServiceDumper implements DumperInterface EOF; } - public function getProxyCode(Definition $definition, string $id = null): string + public function getProxyCode(Definition $definition, ?string $id = null): string { if (!$this->isProxyCandidate($definition, $asGhostObject, $id)) { throw new InvalidArgumentException(sprintf('Cannot instantiate lazy proxy for service "%s".', $id ?? $definition->getClass())); @@ -105,7 +105,7 @@ final class LazyServiceDumper implements DumperInterface if ($asGhostObject) { try { - return 'class '.$proxyClass.ProxyHelper::generateLazyGhost($class); + return (\PHP_VERSION_ID >= 80200 && $class?->isReadOnly() ? 'readonly ' : '').'class '.$proxyClass.ProxyHelper::generateLazyGhost($class); } catch (LogicException $e) { throw new InvalidArgumentException(sprintf('Cannot generate lazy ghost for service "%s".', $id ?? $definition->getClass()), 0, $e); } @@ -139,7 +139,7 @@ final class LazyServiceDumper implements DumperInterface } } - public function getProxyClass(Definition $definition, bool $asGhostObject, \ReflectionClass &$class = null): string + public function getProxyClass(Definition $definition, bool $asGhostObject, ?\ReflectionClass &$class = null): string { $class = 'object' !== $definition->getClass() ? $definition->getClass() : 'stdClass'; $class = new \ReflectionClass($class); diff --git a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php b/lib/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php index daa6fed79..c987b19d4 100644 --- a/lib/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php +++ b/lib/symfony/dependency-injection/LazyProxy/PhpDumper/NullDumper.php @@ -22,7 +22,7 @@ use Symfony\Component\DependencyInjection\Definition; */ class NullDumper implements DumperInterface { - public function isProxyCandidate(Definition $definition, bool &$asGhostObject = null, string $id = null): bool + public function isProxyCandidate(Definition $definition, ?bool &$asGhostObject = null, ?string $id = null): bool { return $asGhostObject = false; } @@ -32,7 +32,7 @@ class NullDumper implements DumperInterface return ''; } - public function getProxyCode(Definition $definition, string $id = null): string + public function getProxyCode(Definition $definition, ?string $id = null): string { return ''; } diff --git a/lib/symfony/dependency-injection/LazyProxy/ProxyHelper.php b/lib/symfony/dependency-injection/LazyProxy/ProxyHelper.php index bde7d6a3f..59dc5aa82 100644 --- a/lib/symfony/dependency-injection/LazyProxy/ProxyHelper.php +++ b/lib/symfony/dependency-injection/LazyProxy/ProxyHelper.php @@ -23,7 +23,7 @@ class ProxyHelper /** * @return string|null The FQCN or builtin name of the type hint, or null when the type hint references an invalid self|parent context */ - public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionParameter $p = null, bool $noBuiltin = false): ?string + public static function getTypeHint(\ReflectionFunctionAbstract $r, ?\ReflectionParameter $p = null, bool $noBuiltin = false): ?string { if ($p instanceof \ReflectionParameter) { $type = $p->getType(); diff --git a/lib/symfony/dependency-injection/Loader/ClosureLoader.php b/lib/symfony/dependency-injection/Loader/ClosureLoader.php index 94305ae94..1e3061d4f 100644 --- a/lib/symfony/dependency-injection/Loader/ClosureLoader.php +++ b/lib/symfony/dependency-injection/Loader/ClosureLoader.php @@ -25,18 +25,18 @@ class ClosureLoader extends Loader { private ContainerBuilder $container; - public function __construct(ContainerBuilder $container, string $env = null) + public function __construct(ContainerBuilder $container, ?string $env = null) { $this->container = $container; parent::__construct($env); } - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { return $resource($this->container, $this->env); } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { return $resource instanceof \Closure; } diff --git a/lib/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php index abf88ff25..02ca9d4cd 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/AbstractServiceConfigurator.php @@ -20,7 +20,7 @@ abstract class AbstractServiceConfigurator extends AbstractConfigurator protected $id; private array $defaultTags = []; - public function __construct(ServicesConfigurator $parent, Definition $definition, string $id = null, array $defaultTags = []) + public function __construct(ServicesConfigurator $parent, Definition $definition, ?string $id = null, array $defaultTags = []) { $this->parent = $parent; $this->definition = $definition; @@ -42,7 +42,7 @@ abstract class AbstractServiceConfigurator extends AbstractConfigurator /** * Registers a service. */ - final public function set(?string $id, string $class = null): ServiceConfigurator + final public function set(?string $id, ?string $class = null): ServiceConfigurator { $this->__destruct(); @@ -106,7 +106,7 @@ abstract class AbstractServiceConfigurator extends AbstractConfigurator /** * Registers a service. */ - final public function __invoke(string $id, string $class = null): ServiceConfigurator + final public function __invoke(string $id, ?string $class = null): ServiceConfigurator { $this->__destruct(); diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php index 52d03fb09..50768171a 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php @@ -38,7 +38,7 @@ class ContainerConfigurator extends AbstractConfigurator private int $anonymousCount = 0; private ?string $env; - public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path, string $file, string $env = null) + public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path, string $file, ?string $env = null) { $this->container = $container; $this->loader = $loader; @@ -58,7 +58,7 @@ class ContainerConfigurator extends AbstractConfigurator $this->container->loadFromExtension($namespace, static::processValue($config)); } - final public function import(string $resource, string $type = null, bool|string $ignoreErrors = false): void + final public function import(string $resource, ?string $type = null, bool|string $ignoreErrors = false): void { $this->loader->setCurrentDir(\dirname($this->path)); $this->loader->import($resource, $type, $ignoreErrors, $this->file); @@ -111,7 +111,7 @@ function service(string $serviceId): ReferenceConfigurator /** * Creates an inline service. */ -function inline_service(string $class = null): InlineServiceConfigurator +function inline_service(?string $class = null): InlineServiceConfigurator { return new InlineServiceConfigurator(new Definition($class)); } @@ -145,7 +145,7 @@ function iterator(array $values): IteratorArgument /** * Creates a lazy iterator by tag name. */ -function tagged_iterator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = true): TaggedIteratorArgument +function tagged_iterator(string $tag, ?string $indexAttribute = null, ?string $defaultIndexMethod = null, ?string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = true): TaggedIteratorArgument { return new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, false, $defaultPriorityMethod, (array) $exclude, $excludeSelf); } @@ -153,7 +153,7 @@ function tagged_iterator(string $tag, string $indexAttribute = null, string $def /** * Creates a service locator by tag name. */ -function tagged_locator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = true): ServiceLocatorArgument +function tagged_locator(string $tag, ?string $indexAttribute = null, ?string $defaultIndexMethod = null, ?string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = true): ServiceLocatorArgument { return new ServiceLocatorArgument(new TaggedIteratorArgument($tag, $indexAttribute, $defaultIndexMethod, true, $defaultPriorityMethod, (array) $exclude, $excludeSelf)); } diff --git a/lib/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php index 2236cd77a..1f26c9788 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/DefaultsConfigurator.php @@ -28,7 +28,7 @@ class DefaultsConfigurator extends AbstractServiceConfigurator private ?string $path; - public function __construct(ServicesConfigurator $parent, Definition $definition, string $path = null) + public function __construct(ServicesConfigurator $parent, Definition $definition, ?string $path = null) { parent::__construct($parent, $definition, null, []); diff --git a/lib/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php index 2db004051..9de0baa4c 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/InstanceofConfigurator.php @@ -33,7 +33,7 @@ class InstanceofConfigurator extends AbstractServiceConfigurator private ?string $path; - public function __construct(ServicesConfigurator $parent, Definition $definition, string $id, string $path = null) + public function __construct(ServicesConfigurator $parent, Definition $definition, string $id, ?string $path = null) { parent::__construct($parent, $definition, $id, []); diff --git a/lib/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php index 4ab957a85..5d844722d 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/PrototypeConfigurator.php @@ -44,7 +44,7 @@ class PrototypeConfigurator extends AbstractServiceConfigurator private bool $allowParent; private ?string $path; - public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, string $namespace, string $resource, bool $allowParent, string $path = null) + public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, string $namespace, string $resource, bool $allowParent, ?string $path = null) { $definition = new Definition(); if (!$defaults->isPublic() || !$defaults->isPrivate()) { diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php index 9042ed1d6..57f498acf 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/ServiceConfigurator.php @@ -49,7 +49,7 @@ class ServiceConfigurator extends AbstractServiceConfigurator private ?string $path; private bool $destructed = false; - public function __construct(ContainerBuilder $container, array $instanceof, bool $allowParent, ServicesConfigurator $parent, Definition $definition, ?string $id, array $defaultTags, string $path = null) + public function __construct(ContainerBuilder $container, array $instanceof, bool $allowParent, ServicesConfigurator $parent, Definition $definition, ?string $id, array $defaultTags, ?string $path = null) { $this->container = $container; $this->instanceof = $instanceof; diff --git a/lib/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php index ee4d1ad16..0c2e5a461 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/ServicesConfigurator.php @@ -34,7 +34,7 @@ class ServicesConfigurator extends AbstractConfigurator private string $anonymousHash; private int $anonymousCount; - public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, string $path = null, int &$anonymousCount = 0) + public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof, ?string $path = null, int &$anonymousCount = 0) { $this->defaults = new Definition(); $this->container = $container; @@ -70,7 +70,7 @@ class ServicesConfigurator extends AbstractConfigurator * @param string|null $id The service id, or null to create an anonymous service * @param string|null $class The class of the service, or null when $id is also the class name */ - final public function set(?string $id, string $class = null): ServiceConfigurator + final public function set(?string $id, ?string $class = null): ServiceConfigurator { $defaults = $this->defaults; $definition = new Definition(); @@ -180,7 +180,7 @@ class ServicesConfigurator extends AbstractConfigurator /** * Registers a service. */ - final public function __invoke(string $id, string $class = null): ServiceConfigurator + final public function __invoke(string $id, ?string $class = null): ServiceConfigurator { return $this->set($id, $class); } diff --git a/lib/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php b/lib/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php index ae6d3c948..afb56ae3d 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/Traits/DecorateTrait.php @@ -25,7 +25,7 @@ trait DecorateTrait * * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals */ - final public function decorate(?string $id, string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): static + final public function decorate(?string $id, ?string $renamedId = null, int $priority = 0, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE): static { $this->definition->setDecoratedService($id, $renamedId, $priority, $invalidBehavior); diff --git a/lib/symfony/dependency-injection/Loader/DirectoryLoader.php b/lib/symfony/dependency-injection/Loader/DirectoryLoader.php index 1b5e81d19..d435366f0 100644 --- a/lib/symfony/dependency-injection/Loader/DirectoryLoader.php +++ b/lib/symfony/dependency-injection/Loader/DirectoryLoader.php @@ -18,7 +18,7 @@ namespace Symfony\Component\DependencyInjection\Loader; */ class DirectoryLoader extends FileLoader { - public function load(mixed $file, string $type = null): mixed + public function load(mixed $file, ?string $type = null): mixed { $file = rtrim($file, '/'); $path = $this->locator->locate($file); @@ -39,7 +39,7 @@ class DirectoryLoader extends FileLoader return null; } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { if ('directory' === $type) { return true; diff --git a/lib/symfony/dependency-injection/Loader/FileLoader.php b/lib/symfony/dependency-injection/Loader/FileLoader.php index 4b56c1788..9baedb4e8 100644 --- a/lib/symfony/dependency-injection/Loader/FileLoader.php +++ b/lib/symfony/dependency-injection/Loader/FileLoader.php @@ -46,7 +46,7 @@ abstract class FileLoader extends BaseFileLoader protected $aliases = []; protected $autoRegisterAliasesForSinglyImplementedInterfaces = true; - public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, string $env = null) + public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, ?string $env = null) { $this->container = $container; @@ -56,7 +56,7 @@ abstract class FileLoader extends BaseFileLoader /** * @param bool|string $ignoreErrors Whether errors should be ignored; pass "not_found" to ignore only when the loaded resource is not found */ - public function import(mixed $resource, string $type = null, bool|string $ignoreErrors = false, string $sourceResource = null, $exclude = null): mixed + public function import(mixed $resource, ?string $type = null, bool|string $ignoreErrors = false, ?string $sourceResource = null, $exclude = null): mixed { $args = \func_get_args(); @@ -98,7 +98,7 @@ abstract class FileLoader extends BaseFileLoader * * @return void */ - public function registerClasses(Definition $prototype, string $namespace, string $resource, string|array $exclude = null/* , string $source = null */) + public function registerClasses(Definition $prototype, string $namespace, string $resource, string|array|null $exclude = null/* , string $source = null */) { if (!str_ends_with($namespace, '\\')) { throw new InvalidArgumentException(sprintf('Namespace prefix must end with a "\\": "%s".', $namespace)); diff --git a/lib/symfony/dependency-injection/Loader/GlobFileLoader.php b/lib/symfony/dependency-injection/Loader/GlobFileLoader.php index 50349b257..4716f11a7 100644 --- a/lib/symfony/dependency-injection/Loader/GlobFileLoader.php +++ b/lib/symfony/dependency-injection/Loader/GlobFileLoader.php @@ -18,7 +18,7 @@ namespace Symfony\Component\DependencyInjection\Loader; */ class GlobFileLoader extends FileLoader { - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { foreach ($this->glob($resource, false, $globResource) as $path => $info) { $this->import($path); @@ -29,7 +29,7 @@ class GlobFileLoader extends FileLoader return null; } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { return 'glob' === $type; } diff --git a/lib/symfony/dependency-injection/Loader/IniFileLoader.php b/lib/symfony/dependency-injection/Loader/IniFileLoader.php index c177790e3..424fbdd51 100644 --- a/lib/symfony/dependency-injection/Loader/IniFileLoader.php +++ b/lib/symfony/dependency-injection/Loader/IniFileLoader.php @@ -21,7 +21,7 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; */ class IniFileLoader extends FileLoader { - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { $path = $this->locator->locate($resource); @@ -55,7 +55,7 @@ class IniFileLoader extends FileLoader return null; } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { if (!\is_string($resource)) { return false; diff --git a/lib/symfony/dependency-injection/Loader/PhpFileLoader.php b/lib/symfony/dependency-injection/Loader/PhpFileLoader.php index e56fb5156..cdaf8ca12 100644 --- a/lib/symfony/dependency-injection/Loader/PhpFileLoader.php +++ b/lib/symfony/dependency-injection/Loader/PhpFileLoader.php @@ -36,13 +36,13 @@ class PhpFileLoader extends FileLoader protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; private ?ConfigBuilderGeneratorInterface $generator; - public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, string $env = null, ConfigBuilderGeneratorInterface $generator = null) + public function __construct(ContainerBuilder $container, FileLocatorInterface $locator, ?string $env = null, ?ConfigBuilderGeneratorInterface $generator = null) { parent::__construct($container, $locator, $env); $this->generator = $generator; } - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { // the container and loader variables are exposed to the included file below $container = $this->container; @@ -71,7 +71,7 @@ class PhpFileLoader extends FileLoader return null; } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { if (!\is_string($resource)) { return false; diff --git a/lib/symfony/dependency-injection/Loader/XmlFileLoader.php b/lib/symfony/dependency-injection/Loader/XmlFileLoader.php index b6eb6732b..574ea5539 100644 --- a/lib/symfony/dependency-injection/Loader/XmlFileLoader.php +++ b/lib/symfony/dependency-injection/Loader/XmlFileLoader.php @@ -41,7 +41,7 @@ class XmlFileLoader extends FileLoader protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { $path = $this->locator->locate($resource); @@ -68,7 +68,7 @@ class XmlFileLoader extends FileLoader return null; } - private function loadXml(\DOMDocument $xml, string $path, \DOMNode $root = null): void + private function loadXml(\DOMDocument $xml, string $path, ?\DOMNode $root = null): void { $defaults = $this->getServiceDefaults($xml, $path, $root); @@ -93,7 +93,7 @@ class XmlFileLoader extends FileLoader } } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { if (!\is_string($resource)) { return false; @@ -106,19 +106,19 @@ class XmlFileLoader extends FileLoader return 'xml' === $type; } - private function parseParameters(\DOMDocument $xml, string $file, \DOMNode $root = null): void + private function parseParameters(\DOMDocument $xml, string $file, ?\DOMNode $root = null): void { if ($parameters = $this->getChildren($root ?? $xml->documentElement, 'parameters')) { $this->container->getParameterBag()->add($this->getArgumentsAsPhp($parameters[0], 'parameter', $file)); } } - private function parseImports(\DOMDocument $xml, string $file, \DOMNode $root = null): void + private function parseImports(\DOMDocument $xml, string $file, ?\DOMNode $root = null): void { $xpath = new \DOMXPath($xml); $xpath->registerNamespace('container', self::NS); - if (false === $imports = $xpath->query('.//container:imports/container:import', $root)) { + if (false === $imports = $xpath->query('./container:imports/container:import', $root)) { return; } @@ -129,19 +129,19 @@ class XmlFileLoader extends FileLoader } } - private function parseDefinitions(\DOMDocument $xml, string $file, Definition $defaults, \DOMNode $root = null): void + private function parseDefinitions(\DOMDocument $xml, string $file, Definition $defaults, ?\DOMNode $root = null): void { $xpath = new \DOMXPath($xml); $xpath->registerNamespace('container', self::NS); - if (false === $services = $xpath->query('.//container:services/container:service|.//container:services/container:prototype|.//container:services/container:stack', $root)) { + if (false === $services = $xpath->query('./container:services/container:service|./container:services/container:prototype|./container:services/container:stack', $root)) { return; } $this->setCurrentDir(\dirname($file)); $this->instanceof = []; $this->isLoadingInstanceof = true; - $instanceof = $xpath->query('.//container:services/container:instanceof', $root); + $instanceof = $xpath->query('./container:services/container:instanceof', $root); foreach ($instanceof as $service) { $this->setDefinition((string) $service->getAttribute('id'), $this->parseDefinition($service, $file, new Definition())); } @@ -187,12 +187,12 @@ class XmlFileLoader extends FileLoader } } - private function getServiceDefaults(\DOMDocument $xml, string $file, \DOMNode $root = null): Definition + private function getServiceDefaults(\DOMDocument $xml, string $file, ?\DOMNode $root = null): Definition { $xpath = new \DOMXPath($xml); $xpath->registerNamespace('container', self::NS); - if (null === $defaultsNode = $xpath->query('.//container:services/container:defaults', $root)->item(0)) { + if (null === $defaultsNode = $xpath->query('./container:services/container:defaults', $root)->item(0)) { return new Definition(); } @@ -458,7 +458,33 @@ class XmlFileLoader extends FileLoader try { $dom = XmlUtils::loadFile($file, $this->validateSchema(...)); } catch (\InvalidArgumentException $e) { - throw new InvalidArgumentException(sprintf('Unable to parse file "%s": ', $file).$e->getMessage(), $e->getCode(), $e); + $invalidSecurityElements = []; + $errors = explode("\n", $e->getMessage()); + foreach ($errors as $i => $error) { + if (preg_match("#^\[ERROR 1871] Element '\{http://symfony\.com/schema/dic/security}([^']+)'#", $error, $matches)) { + $invalidSecurityElements[$i] = $matches[1]; + } + } + if ($invalidSecurityElements) { + $dom = XmlUtils::loadFile($file); + + foreach ($invalidSecurityElements as $errorIndex => $tagName) { + foreach ($dom->getElementsByTagNameNS('http://symfony.com/schema/dic/security', $tagName) as $element) { + if (!$parent = $element->parentNode) { + continue; + } + if ('http://symfony.com/schema/dic/security' !== $parent->namespaceURI) { + continue; + } + if ('provider' === $parent->localName || 'firewall' === $parent->localName) { + unset($errors[$errorIndex]); + } + } + } + } + if ($errors) { + throw new InvalidArgumentException(sprintf('Unable to parse file "%s": ', $file).implode("\n", $errors), $e->getCode(), $e); + } } $this->validateExtensions($dom, $file); @@ -469,7 +495,7 @@ class XmlFileLoader extends FileLoader /** * Processes anonymous services. */ - private function processAnonymousServices(\DOMDocument $xml, string $file, \DOMNode $root = null): void + private function processAnonymousServices(\DOMDocument $xml, string $file, ?\DOMNode $root = null): void { $definitions = []; $count = 0; @@ -858,6 +884,6 @@ EOF */ public static function convertDomElementToArray(\DOMElement $element): mixed { - return XmlUtils::convertDomElementToArray($element); + return XmlUtils::convertDomElementToArray($element, false); } } diff --git a/lib/symfony/dependency-injection/Loader/YamlFileLoader.php b/lib/symfony/dependency-injection/Loader/YamlFileLoader.php index 822b45ef7..ae5a625df 100644 --- a/lib/symfony/dependency-injection/Loader/YamlFileLoader.php +++ b/lib/symfony/dependency-injection/Loader/YamlFileLoader.php @@ -117,7 +117,7 @@ class YamlFileLoader extends FileLoader protected $autoRegisterAliasesForSinglyImplementedInterfaces = false; - public function load(mixed $resource, string $type = null): mixed + public function load(mixed $resource, ?string $type = null): mixed { $path = $this->locator->locate($resource); @@ -181,7 +181,7 @@ class YamlFileLoader extends FileLoader } } - public function supports(mixed $resource, string $type = null): bool + public function supports(mixed $resource, ?string $type = null): bool { if (!\is_string($resource)) { return false; @@ -450,8 +450,9 @@ class YamlFileLoader extends FileLoader return $return ? $alias : $this->container->setAlias($id, $alias); } + $changes = []; if (null !== $definition) { - // no-op + $changes = $definition->getChanges(); } elseif ($this->isLoadingInstanceof) { $definition = new ChildDefinition(''); } elseif (isset($service['parent'])) { @@ -474,7 +475,7 @@ class YamlFileLoader extends FileLoader $definition->setAutoconfigured($defaults['autoconfigure']); } - $definition->setChanges([]); + $definition->setChanges($changes); if (isset($service['class'])) { $definition->setClass($service['class']); @@ -556,7 +557,7 @@ class YamlFileLoader extends FileLoader } if (\is_string($k)) { - throw new InvalidArgumentException(sprintf('Invalid method call for service "%s", did you forgot a leading dash before "%s: ..." in "%s"?', $id, $k, $file)); + throw new InvalidArgumentException(sprintf('Invalid method call for service "%s", did you forget a leading dash before "%s: ..." in "%s"?', $id, $k, $file)); } if (isset($call['method']) && \is_string($call['method'])) { diff --git a/lib/symfony/dependency-injection/ServiceLocator.php b/lib/symfony/dependency-injection/ServiceLocator.php index f36bfe5cb..45530f798 100644 --- a/lib/symfony/dependency-injection/ServiceLocator.php +++ b/lib/symfony/dependency-injection/ServiceLocator.php @@ -138,7 +138,7 @@ class ServiceLocator implements ServiceProviderInterface, \Countable return new ServiceCircularReferenceException($id, $path); } - private function formatAlternatives(array $alternatives = null, string $separator = 'and'): string + private function formatAlternatives(?array $alternatives = null, string $separator = 'and'): string { $format = '"%s"%s'; if (null === $alternatives) { diff --git a/lib/symfony/dependency-injection/TypedReference.php b/lib/symfony/dependency-injection/TypedReference.php index 9b431cd65..1c932c313 100644 --- a/lib/symfony/dependency-injection/TypedReference.php +++ b/lib/symfony/dependency-injection/TypedReference.php @@ -29,7 +29,7 @@ class TypedReference extends Reference * @param string|null $name The name of the argument targeting the service * @param array $attributes The attributes to be used */ - public function __construct(string $id, string $type, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, string $name = null, array $attributes = []) + public function __construct(string $id, string $type, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, ?string $name = null, array $attributes = []) { $this->name = $type === $id ? $name : null; parent::__construct($id, $invalidBehavior); diff --git a/lib/symfony/dependency-injection/composer.json b/lib/symfony/dependency-injection/composer.json index dc4a9feaf..86b05b917 100644 --- a/lib/symfony/dependency-injection/composer.json +++ b/lib/symfony/dependency-injection/composer.json @@ -20,7 +20,7 @@ "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10|^7.0" + "symfony/var-exporter": "^6.4.20|^7.2.5" }, "require-dev": { "symfony/yaml": "^5.4|^6.0|^7.0", diff --git a/lib/symfony/deprecation-contracts/composer.json b/lib/symfony/deprecation-contracts/composer.json index c6d02d874..5533b5c3f 100644 --- a/lib/symfony/deprecation-contracts/composer.json +++ b/lib/symfony/deprecation-contracts/composer.json @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.6-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/lib/symfony/dotenv/Command/DebugCommand.php b/lib/symfony/dotenv/Command/DebugCommand.php index 0da80245e..0315b77aa 100644 --- a/lib/symfony/dotenv/Command/DebugCommand.php +++ b/lib/symfony/dotenv/Command/DebugCommand.php @@ -15,6 +15,7 @@ use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Completion\CompletionInput; use Symfony\Component\Console\Completion\CompletionSuggestions; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -80,21 +81,35 @@ EOT return 1; } - $envFiles = $this->getEnvFiles(); - $availableFiles = array_filter($envFiles, fn (string $file) => is_file($this->getFilePath($file))); + if (!$filePath = $_SERVER['SYMFONY_DOTENV_PATH'] ?? null) { + $dotenvPath = $this->projectDirectory; - if (\in_array('.env.local.php', $availableFiles, true)) { - $io->warning('Due to existing dump file (.env.local.php) all other dotenv files are skipped.'); + if (is_file($composerFile = $this->projectDirectory.'/composer.json')) { + $runtimeConfig = (json_decode(file_get_contents($composerFile), true))['extra']['runtime'] ?? []; + + if (isset($runtimeConfig['dotenv_path'])) { + $dotenvPath = $this->projectDirectory.'/'.$runtimeConfig['dotenv_path']; + } + } + + $filePath = $dotenvPath.'/.env'; } - if (is_file($this->getFilePath('.env')) && is_file($this->getFilePath('.env.dist'))) { - $io->warning('The file .env.dist gets skipped due to the existence of .env.'); + $envFiles = $this->getEnvFiles($filePath); + $availableFiles = array_filter($envFiles, 'is_file'); + + if (\in_array(sprintf('%s.local.php', $filePath), $availableFiles, true)) { + $io->warning(sprintf('Due to existing dump file (%s.local.php) all other dotenv files are skipped.', $this->getRelativeName($filePath))); + } + + if (is_file($filePath) && is_file(sprintf('%s.dist', $filePath))) { + $io->warning(sprintf('The file %s.dist gets skipped due to the existence of %1$s.', $this->getRelativeName($filePath))); } $io->section('Scanned Files (in descending priority)'); - $io->listing(array_map(static fn (string $envFile) => \in_array($envFile, $availableFiles, true) - ? sprintf('✓ %s', $envFile) - : sprintf('⨯ %s', $envFile), $envFiles)); + $io->listing(array_map(fn (string $envFile) => \in_array($envFile, $availableFiles, true) + ? sprintf('✓ %s', $this->getRelativeName($envFile)) + : sprintf('⨯ %s', $this->getRelativeName($envFile)), $envFiles)); $nameFilter = $input->getArgument('filter'); $variables = $this->getVariables($availableFiles, $nameFilter); @@ -103,8 +118,8 @@ EOT if ($variables || null === $nameFilter) { $io->table( - array_merge(['Variable', 'Value'], $availableFiles), - $this->getVariables($availableFiles, $nameFilter) + array_merge(['Variable', 'Value'], array_map($this->getRelativeName(...), $availableFiles)), + $variables ); $io->comment('Note that values might be different between web and CLI.'); @@ -124,75 +139,84 @@ EOT private function getVariables(array $envFiles, ?string $nameFilter): array { - $vars = $this->getAvailableVars(); - - $output = []; + $variables = []; $fileValues = []; - foreach ($vars as $var) { + $dotenvVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? '')); + + foreach ($envFiles as $envFile) { + $fileValues[$envFile] = $this->loadValues($envFile); + $variables += $fileValues[$envFile]; + } + + foreach ($variables as $var => $varDetails) { if (null !== $nameFilter && 0 !== stripos($var, $nameFilter)) { + unset($variables[$var]); continue; } - $realValue = $_SERVER[$var]; - $varDetails = [$var, $realValue]; - foreach ($envFiles as $envFile) { - $values = $fileValues[$envFile] ??= $this->loadValues($envFile); + $realValue = $_SERVER[$var] ?? ''; + $varDetails = [$var, ''.OutputFormatter::escape($realValue).'']; + $varSeen = !isset($dotenvVars[$var]); - $varString = $values[$var] ?? 'n/a'; - $shortenedVar = $this->getHelper('formatter')->truncate($varString, 30); - $varDetails[] = $varString === $realValue ? ''.$shortenedVar.'' : $shortenedVar; + foreach ($envFiles as $envFile) { + if (null === $value = $fileValues[$envFile][$var] ?? null) { + $varDetails[] = 'n/a'; + continue; + } + + $shortenedValue = OutputFormatter::escape($this->getHelper('formatter')->truncate($value, 30)); + $varDetails[] = $value === $realValue && !$varSeen ? ''.$shortenedValue.'' : $shortenedValue; + $varSeen = $varSeen || $value === $realValue; } - $output[] = $varDetails; + $variables[$var] = $varDetails; } - return $output; + ksort($variables); + + return $variables; } private function getAvailableVars(): array { - $dotenvVars = $_SERVER['SYMFONY_DOTENV_VARS'] ?? ''; + $filePath = $_SERVER['SYMFONY_DOTENV_PATH'] ?? $this->projectDirectory.\DIRECTORY_SEPARATOR.'.env'; + $envFiles = $this->getEnvFiles($filePath); - if ('' === $dotenvVars) { - return []; - } - - $vars = explode(',', $dotenvVars); - sort($vars); - - return $vars; + return array_keys($this->getVariables(array_filter($envFiles, 'is_file'), null)); } - private function getEnvFiles(): array + private function getEnvFiles(string $filePath): array { $files = [ - '.env.local.php', - sprintf('.env.%s.local', $this->kernelEnvironment), - sprintf('.env.%s', $this->kernelEnvironment), + sprintf('%s.local.php', $filePath), + sprintf('%s.%s.local', $filePath, $this->kernelEnvironment), + sprintf('%s.%s', $filePath, $this->kernelEnvironment), ]; if ('test' !== $this->kernelEnvironment) { - $files[] = '.env.local'; + $files[] = sprintf('%s.local', $filePath); } - if (!is_file($this->getFilePath('.env')) && is_file($this->getFilePath('.env.dist'))) { - $files[] = '.env.dist'; + if (!is_file($filePath) && is_file(sprintf('%s.dist', $filePath))) { + $files[] = sprintf('%s.dist', $filePath); } else { - $files[] = '.env'; + $files[] = $filePath; } return $files; } - private function getFilePath(string $file): string + private function getRelativeName(string $filePath): string { - return $this->projectDirectory.\DIRECTORY_SEPARATOR.$file; + if (str_starts_with($filePath, $this->projectDirectory)) { + return substr($filePath, \strlen($this->projectDirectory) + 1); + } + + return basename($filePath); } - private function loadValues(string $file): array + private function loadValues(string $filePath): array { - $filePath = $this->getFilePath($file); - if (str_ends_with($filePath, '.php')) { return include $filePath; } diff --git a/lib/symfony/dotenv/Command/DotenvDumpCommand.php b/lib/symfony/dotenv/Command/DotenvDumpCommand.php index 051f4b05a..cd0fb5d18 100644 --- a/lib/symfony/dotenv/Command/DotenvDumpCommand.php +++ b/lib/symfony/dotenv/Command/DotenvDumpCommand.php @@ -32,7 +32,7 @@ final class DotenvDumpCommand extends Command private string $projectDir; private ?string $defaultEnv; - public function __construct(string $projectDir, string $defaultEnv = null) + public function __construct(string $projectDir, ?string $defaultEnv = null) { $this->projectDir = $projectDir; $this->defaultEnv = $defaultEnv; @@ -95,10 +95,11 @@ EOF; private function loadEnv(string $dotenvPath, string $env, array $config): array { - $dotenv = new Dotenv(); $envKey = $config['env_var_name'] ?? 'APP_ENV'; $testEnvs = $config['test_envs'] ?? ['test']; + $dotenv = new Dotenv($envKey); + $globalsBackup = [$_SERVER, $_ENV]; unset($_SERVER[$envKey]); $_ENV = [$envKey => $env]; diff --git a/lib/symfony/dotenv/Dotenv.php b/lib/symfony/dotenv/Dotenv.php index 9b905f31c..88bda299d 100644 --- a/lib/symfony/dotenv/Dotenv.php +++ b/lib/symfony/dotenv/Dotenv.php @@ -98,7 +98,7 @@ final class Dotenv * @throws FormatException when a file has a syntax error * @throws PathException when a file does not exist or is not readable */ - public function loadEnv(string $path, string $envKey = null, string $defaultEnv = 'dev', array $testEnvs = ['test'], bool $overrideExistingVars = false): void + public function loadEnv(string $path, ?string $envKey = null, string $defaultEnv = 'dev', array $testEnvs = ['test'], bool $overrideExistingVars = false): void { $k = $envKey ?? $this->envKey; @@ -480,7 +480,7 @@ final class Dotenv (?!\() # no opening parenthesis (?P\{)? # optional brace (?P'.self::VARNAME_REGEX.')? # var name - (?P:[-=][^\}]++)? # optional default value + (?P:[-=][^\}]*+)? # optional default value (?P\})? # optional closing brace /x'; @@ -553,7 +553,13 @@ final class Dotenv throw new PathException($path); } - $this->populate($this->parse(file_get_contents($path), $path), $overrideExistingVars); + $data = file_get_contents($path); + + if ("\xEF\xBB\xBF" === substr($data, 0, 3)) { + throw new FormatException('Loading files starting with a byte-order-mark (BOM) is not supported.', new FormatExceptionContext($data, $path, 1, 0)); + } + + $this->populate($this->parse($data, $path), $overrideExistingVars); } } } diff --git a/lib/symfony/dotenv/Exception/FormatException.php b/lib/symfony/dotenv/Exception/FormatException.php index 8f1aa84b2..684d98c5a 100644 --- a/lib/symfony/dotenv/Exception/FormatException.php +++ b/lib/symfony/dotenv/Exception/FormatException.php @@ -20,7 +20,7 @@ final class FormatException extends \LogicException implements ExceptionInterfac { private FormatExceptionContext $context; - public function __construct(string $message, FormatExceptionContext $context, int $code = 0, \Throwable $previous = null) + public function __construct(string $message, FormatExceptionContext $context, int $code = 0, ?\Throwable $previous = null) { $this->context = $context; diff --git a/lib/symfony/dotenv/Exception/PathException.php b/lib/symfony/dotenv/Exception/PathException.php index 4a4d71722..e432b2e33 100644 --- a/lib/symfony/dotenv/Exception/PathException.php +++ b/lib/symfony/dotenv/Exception/PathException.php @@ -18,7 +18,7 @@ namespace Symfony\Component\Dotenv\Exception; */ final class PathException extends \RuntimeException implements ExceptionInterface { - public function __construct(string $path, int $code = 0, \Throwable $previous = null) + public function __construct(string $path, int $code = 0, ?\Throwable $previous = null) { parent::__construct(sprintf('Unable to read the "%s" environment file.', $path), $code, $previous); } diff --git a/lib/symfony/error-handler/Debug.php b/lib/symfony/error-handler/Debug.php index d54a38c4c..b090040d0 100644 --- a/lib/symfony/error-handler/Debug.php +++ b/lib/symfony/error-handler/Debug.php @@ -20,7 +20,7 @@ class Debug { public static function enable(): ErrorHandler { - error_reporting(-1); + error_reporting(\E_ALL & ~\E_DEPRECATED & ~\E_USER_DEPRECATED); if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { ini_set('display_errors', 0); diff --git a/lib/symfony/error-handler/DebugClassLoader.php b/lib/symfony/error-handler/DebugClassLoader.php index 16af2d063..3f2a13624 100644 --- a/lib/symfony/error-handler/DebugClassLoader.php +++ b/lib/symfony/error-handler/DebugClassLoader.php @@ -18,8 +18,10 @@ use Mockery\MockInterface; use Phake\IMock; use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation; use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\MockObject\Stub; use Prophecy\Prophecy\ProphecySubjectInterface; use ProxyManager\Proxy\ProxyInterface; +use Symfony\Component\DependencyInjection\Argument\LazyClosure; use Symfony\Component\ErrorHandler\Internal\TentativeTypes; use Symfony\Component\VarExporter\LazyObjectInterface; @@ -252,6 +254,7 @@ class DebugClassLoader for (; $i < \count($symbols); ++$i) { if (!is_subclass_of($symbols[$i], MockObject::class) + && !is_subclass_of($symbols[$i], Stub::class) && !is_subclass_of($symbols[$i], ProphecySubjectInterface::class) && !is_subclass_of($symbols[$i], Proxy::class) && !is_subclass_of($symbols[$i], ProxyInterface::class) @@ -259,6 +262,7 @@ class DebugClassLoader && !is_subclass_of($symbols[$i], LegacyProxy::class) && !is_subclass_of($symbols[$i], MockInterface::class) && !is_subclass_of($symbols[$i], IMock::class) + && !(is_subclass_of($symbols[$i], LazyClosure::class) && str_contains($symbols[$i], "@anonymous\0")) ) { $loader->checkClass($symbols[$i]); } @@ -307,7 +311,7 @@ class DebugClassLoader $this->checkClass($class, $file); } - private function checkClass(string $class, string $file = null): void + private function checkClass(string $class, ?string $file = null): void { $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); @@ -794,7 +798,7 @@ class DebugClassLoader return $ownInterfaces; } - private function setReturnType(string $types, string $class, string $method, string $filename, ?string $parent, \ReflectionType $returnType = null): void + private function setReturnType(string $types, string $class, string $method, string $filename, ?string $parent, ?\ReflectionType $returnType = null): void { if ('__construct' === $method) { return; @@ -1133,7 +1137,7 @@ EOTXT; $braces = 0; for (; $i < $end; ++$i) { if (!$inClosure) { - $inClosure = str_contains($code[$i], 'function ('); + $inClosure = false !== strpos($code[$i], 'function ('); } if ($inClosure) { diff --git a/lib/symfony/error-handler/Error/FatalError.php b/lib/symfony/error-handler/Error/FatalError.php index a1fd5a995..a0657b7b8 100644 --- a/lib/symfony/error-handler/Error/FatalError.php +++ b/lib/symfony/error-handler/Error/FatalError.php @@ -18,7 +18,7 @@ class FatalError extends \Error /** * @param array $error An array as returned by error_get_last() */ - public function __construct(string $message, int $code, array $error, int $traceOffset = null, bool $traceArgs = true, array $trace = null) + public function __construct(string $message, int $code, array $error, ?int $traceOffset = null, bool $traceArgs = true, ?array $trace = null) { parent::__construct($message, $code); @@ -31,7 +31,7 @@ class FatalError extends \Error } } } elseif (null !== $traceOffset) { - if (\function_exists('xdebug_get_function_stack') && $trace = @xdebug_get_function_stack()) { + if (\function_exists('xdebug_get_function_stack') && \in_array(\ini_get('xdebug.mode'), ['develop', false], true) && $trace = @xdebug_get_function_stack()) { if (0 < $traceOffset) { array_splice($trace, -$traceOffset); } diff --git a/lib/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php b/lib/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php index a98075fe4..b4623cf17 100644 --- a/lib/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php +++ b/lib/symfony/error-handler/ErrorEnhancer/ClassNotFoundErrorEnhancer.php @@ -107,7 +107,8 @@ class ClassNotFoundErrorEnhancer implements ErrorEnhancerInterface private function findClassInPath(string $path, string $class, string $prefix): array { - if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { + $path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path); + if (!$path || !is_dir($path)) { return []; } diff --git a/lib/symfony/error-handler/ErrorHandler.php b/lib/symfony/error-handler/ErrorHandler.php index 1ee29e1b8..052baf27a 100644 --- a/lib/symfony/error-handler/ErrorHandler.php +++ b/lib/symfony/error-handler/ErrorHandler.php @@ -55,7 +55,6 @@ class ErrorHandler \E_USER_DEPRECATED => 'User Deprecated', \E_NOTICE => 'Notice', \E_USER_NOTICE => 'User Notice', - \E_STRICT => 'Runtime Notice', \E_WARNING => 'Warning', \E_USER_WARNING => 'User Warning', \E_COMPILE_WARNING => 'Compile Warning', @@ -73,7 +72,6 @@ class ErrorHandler \E_USER_DEPRECATED => [null, LogLevel::INFO], \E_NOTICE => [null, LogLevel::WARNING], \E_USER_NOTICE => [null, LogLevel::WARNING], - \E_STRICT => [null, LogLevel::WARNING], \E_WARNING => [null, LogLevel::WARNING], \E_USER_WARNING => [null, LogLevel::WARNING], \E_COMPILE_WARNING => [null, LogLevel::WARNING], @@ -108,7 +106,7 @@ class ErrorHandler /** * Registers the error handler. */ - public static function register(self $handler = null, bool $replace = true): self + public static function register(?self $handler = null, bool $replace = true): self { if (null === self::$reservedMemory) { self::$reservedMemory = str_repeat('x', 32768); @@ -179,8 +177,13 @@ class ErrorHandler } } - public function __construct(BufferingLogger $bootstrappingLogger = null, bool $debug = false) + public function __construct(?BufferingLogger $bootstrappingLogger = null, bool $debug = false) { + if (\PHP_VERSION_ID < 80400) { + $this->levels[\E_STRICT] = 'Runtime Notice'; + $this->loggers[\E_STRICT] = [null, LogLevel::WARNING]; + } + if ($bootstrappingLogger) { $this->bootstrappingLogger = $bootstrappingLogger; $this->setDefaultLogger($bootstrappingLogger); @@ -432,7 +435,7 @@ class ErrorHandler return true; } } else { - if (str_contains($message, '@anonymous')) { + if (PHP_VERSION_ID < 80303 && str_contains($message, '@anonymous')) { $backtrace = debug_backtrace(false, 5); for ($i = 1; isset($backtrace[$i]); ++$i) { @@ -440,8 +443,7 @@ class ErrorHandler && ('trigger_error' === $backtrace[$i]['function'] || 'user_error' === $backtrace[$i]['function']) ) { if ($backtrace[$i]['args'][0] !== $message) { - $message = $this->parseAnonymousClass($backtrace[$i]['args'][0]); - $logMessage = $this->levels[$type].': '.$message; + $message = $backtrace[$i]['args'][0]; } break; @@ -449,6 +451,11 @@ class ErrorHandler } } + if (false !== strpos($message, "@anonymous\0")) { + $message = $this->parseAnonymousClass($message); + $logMessage = $this->levels[$type].': '.$message; + } + $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); if ($throw || $this->tracedErrors & $type) { @@ -559,7 +566,7 @@ class ErrorHandler * * @internal */ - public static function handleFatalError(array $error = null): void + public static function handleFatalError(?array $error = null): void { if (null === self::$reservedMemory) { return; @@ -591,6 +598,10 @@ class ErrorHandler set_exception_handler($h); } if (!$handler) { + if (null === $error && $exitCode = self::$exitCode) { + register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); }); + } + return; } if ($handler !== $h) { @@ -626,8 +637,7 @@ class ErrorHandler // Ignore this re-throw } - if ($exit && self::$exitCode) { - $exitCode = self::$exitCode; + if ($exit && $exitCode = self::$exitCode) { register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); }); } } @@ -732,6 +742,6 @@ class ErrorHandler */ private function parseAnonymousClass(string $message): string { - return preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', static fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $message); + return preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', static fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $message); } } diff --git a/lib/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php b/lib/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php index 29fcf835b..ca793b075 100644 --- a/lib/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php +++ b/lib/symfony/error-handler/ErrorRenderer/FileLinkFormatter.php @@ -30,9 +30,9 @@ class FileLinkFormatter private \Closure|string|null $urlFormat; /** - * @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand + * @param string|\Closure $urlFormat The URL format, or a closure that returns it on-demand */ - public function __construct(string|array $fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, string|\Closure $urlFormat = null) + public function __construct(string|array|null $fileLinkFormat = null, ?RequestStack $requestStack = null, ?string $baseDir = null, string|\Closure|null $urlFormat = null) { $fileLinkFormat ??= $_ENV['SYMFONY_IDE'] ?? $_SERVER['SYMFONY_IDE'] ?? ''; diff --git a/lib/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php b/lib/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php index 4e2a99b80..2572a8abd 100644 --- a/lib/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php +++ b/lib/symfony/error-handler/ErrorRenderer/HtmlErrorRenderer.php @@ -47,7 +47,7 @@ class HtmlErrorRenderer implements ErrorRendererInterface * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it * @param string|callable $outputBuffer The output buffer as a string or a callable that should return it */ - public function __construct(bool|callable $debug = false, string $charset = null, string|FileLinkFormatter $fileLinkFormat = null, string $projectDir = null, string|callable $outputBuffer = '', LoggerInterface $logger = null) + public function __construct(bool|callable $debug = false, ?string $charset = null, string|FileLinkFormatter|null $fileLinkFormat = null, ?string $projectDir = null, string|callable $outputBuffer = '', ?LoggerInterface $logger = null) { $this->debug = \is_bool($debug) ? $debug : $debug(...); $this->charset = $charset ?: (\ini_get('default_charset') ?: 'UTF-8'); @@ -61,7 +61,7 @@ class HtmlErrorRenderer implements ErrorRendererInterface { $headers = ['Content-Type' => 'text/html; charset='.$this->charset]; if (\is_bool($this->debug) ? $this->debug : ($this->debug)($exception)) { - $headers['X-Debug-Exception'] = rawurlencode($exception->getMessage()); + $headers['X-Debug-Exception'] = rawurlencode(substr($exception->getMessage(), 0, 2000)); $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine(); } @@ -140,7 +140,7 @@ class HtmlErrorRenderer implements ErrorRendererInterface 'exceptionMessage' => $exceptionMessage, 'statusText' => $statusText, 'statusCode' => $statusCode, - 'logger' => DebugLoggerConfigurator::getDebugLogger($this->logger), + 'logger' => null !== $this->logger && class_exists(DebugLoggerConfigurator::class) ? DebugLoggerConfigurator::getDebugLogger($this->logger) : null, 'currentContent' => \is_string($this->outputBuffer) ? $this->outputBuffer : ($this->outputBuffer)(), ]); } @@ -167,6 +167,8 @@ class HtmlErrorRenderer implements ErrorRendererInterface $formattedValue = ''.strtolower(var_export($item[1], true)).''; } elseif ('resource' === $item[0]) { $formattedValue = 'resource'; + } elseif (preg_match('/[^\x07-\x0D\x1B\x20-\xFF]/', $item[1])) { + $formattedValue = 'binary string'; } else { $formattedValue = str_replace("\n", '', $this->escape(var_export($item[1], true))); } @@ -213,7 +215,7 @@ class HtmlErrorRenderer implements ErrorRendererInterface * @param int $line The line number * @param string $text Use this text for the link rather than the file path */ - private function formatFile(string $file, int $line, string $text = null): string + private function formatFile(string $file, int $line, ?string $text = null): string { $file = trim($file); @@ -229,6 +231,10 @@ class HtmlErrorRenderer implements ErrorRendererInterface $text .= ' at line '.$line; } + if (!file_exists($file)) { + return $text; + } + $link = $this->fileLinkFormat->format($file, $line); return sprintf('%s', $this->escape($link), $text); @@ -250,10 +256,10 @@ class HtmlErrorRenderer implements ErrorRendererInterface if (\PHP_VERSION_ID >= 80300) { // remove main pre/code tags $code = preg_replace('#^\s*(.*)\s*#s', '\\1', $code); - // split multiline code tags - $code = preg_replace_callback('#]++)>((?:[^<]*+\\n)++[^<]*+)#', fn ($m) => "".str_replace("\n", "\n", $m[2]).'', $code); - // Convert spaces to html entities to preserve indentation when rendered - $code = str_replace(' ', ' ', $code); + // split multiline span tags + $code = preg_replace_callback('#]++)>((?:[^<\\n]*+\\n)++[^<]*+)#', function ($m) { + return "".str_replace("\n", "\n", $m[2]).''; + }, $code); $content = explode("\n", $code); } else { // remove main code/span tags @@ -299,7 +305,7 @@ class HtmlErrorRenderer implements ErrorRendererInterface private function formatFileFromText(string $text): string { - return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', fn ($match) => 'in '.$this->formatFile($match[2], $match[3]), $text); + return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', fn ($match) => 'in '.$this->formatFile($match[2], $match[3]), $text) ?? $text; } private function formatLogMessage(string $message, array $context): string diff --git a/lib/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php b/lib/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php index 1f286b784..b09a6e00c 100644 --- a/lib/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php +++ b/lib/symfony/error-handler/ErrorRenderer/SerializerErrorRenderer.php @@ -34,7 +34,7 @@ class SerializerErrorRenderer implements ErrorRendererInterface * formats not supported by Request::getMimeTypes() should be given as mime types * @param bool|callable $debug The debugging mode as a boolean or a callable that should return it */ - public function __construct(SerializerInterface $serializer, string|callable $format, ErrorRendererInterface $fallbackErrorRenderer = null, bool|callable $debug = false) + public function __construct(SerializerInterface $serializer, string|callable $format, ?ErrorRendererInterface $fallbackErrorRenderer = null, bool|callable $debug = false) { $this->serializer = $serializer; $this->format = \is_string($format) ? $format : $format(...); @@ -47,7 +47,7 @@ class SerializerErrorRenderer implements ErrorRendererInterface $headers = ['Vary' => 'Accept']; $debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception); if ($debug) { - $headers['X-Debug-Exception'] = rawurlencode($exception->getMessage()); + $headers['X-Debug-Exception'] = rawurlencode(substr($exception->getMessage(), 0, 2000)); $headers['X-Debug-Exception-File'] = rawurlencode($exception->getFile()).':'.$exception->getLine(); } diff --git a/lib/symfony/error-handler/Exception/FlattenException.php b/lib/symfony/error-handler/Exception/FlattenException.php index ab62b1be3..f8ec1faf0 100644 --- a/lib/symfony/error-handler/Exception/FlattenException.php +++ b/lib/symfony/error-handler/Exception/FlattenException.php @@ -42,12 +42,12 @@ class FlattenException private ?string $asString = null; private Data $dataRepresentation; - public static function create(\Exception $exception, int $statusCode = null, array $headers = []): static + public static function create(\Exception $exception, ?int $statusCode = null, array $headers = []): static { return static::createFromThrowable($exception, $statusCode, $headers); } - public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = []): static + public static function createFromThrowable(\Throwable $exception, ?int $statusCode = null, array $headers = []): static { $e = new static(); $e->setMessage($exception->getMessage()); @@ -85,7 +85,7 @@ class FlattenException return $e; } - public static function createWithDataRepresentation(\Throwable $throwable, int $statusCode = null, array $headers = [], VarCloner $cloner = null): static + public static function createWithDataRepresentation(\Throwable $throwable, ?int $statusCode = null, array $headers = [], ?VarCloner $cloner = null): static { $e = static::createFromThrowable($throwable, $statusCode, $headers); @@ -228,7 +228,7 @@ class FlattenException public function setMessage(string $message): static { if (str_contains($message, "@anonymous\0")) { - $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $message); + $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $message); } $this->message = $message; diff --git a/lib/symfony/error-handler/Resources/assets/css/exception.css b/lib/symfony/error-handler/Resources/assets/css/exception.css index 3e6eae5a9..8c3690720 100644 --- a/lib/symfony/error-handler/Resources/assets/css/exception.css +++ b/lib/symfony/error-handler/Resources/assets/css/exception.css @@ -57,7 +57,7 @@ --page-background: #36393e; --color-text: #e0e0e0; --color-muted: #777; - --color-error: #d43934; + --color-error: #f76864; --tab-background: #404040; --tab-border-color: #737373; --tab-active-border-color: #171717; @@ -80,7 +80,7 @@ --metric-unit-color: #999; --metric-label-background: #777; --metric-label-color: #e0e0e0; - --trace-selected-background: #71663acc; + --trace-selected-background: #5d5227cc; --table-border: #444; --table-background: #333; --table-header: #555; @@ -92,7 +92,7 @@ --background-error: #b0413e; --highlight-comment: #dedede; --highlight-default: var(--base-6); - --highlight-keyword: #ff413c; + --highlight-keyword: #de8986; --highlight-string: #70a6fd; --base-0: #2e3136; --base-1: #444; @@ -349,7 +349,7 @@ header .container { display: flex; justify-content: space-between; } .trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; } .trace-code li + li { margin-top: 5px; } .trace-code li.selected { background: var(--trace-selected-background); margin-top: 2px; } -.trace-code li code { color: var(--base-6); white-space: nowrap; } +.trace-code li code { color: var(--base-6); white-space: pre; } .trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; } diff --git a/lib/symfony/error-handler/Resources/assets/js/exception.js b/lib/symfony/error-handler/Resources/assets/js/exception.js index 22ce675df..89c008334 100644 --- a/lib/symfony/error-handler/Resources/assets/js/exception.js +++ b/lib/symfony/error-handler/Resources/assets/js/exception.js @@ -145,6 +145,12 @@ } addEventListener(toggles[i], 'click', function(e) { + var toggle = e.currentTarget; + + if (e.target.closest('a, span[data-clipboard-text], .sf-toggle') !== toggle) { + return; + } + e.preventDefault(); if ('' !== window.getSelection().toString()) { @@ -152,14 +158,6 @@ return; } - var toggle = e.target || e.srcElement; - - /* needed because when the toggle contains HTML contents, user can click */ - /* on any of those elements instead of their parent '.sf-toggle' element */ - while (!hasClass(toggle, 'sf-toggle')) { - toggle = toggle.parentNode; - } - var element = document.querySelector(toggle.getAttribute('data-toggle-selector')); toggleClass(toggle, 'sf-toggle-on'); @@ -182,22 +180,6 @@ toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; }); - /* Prevents from disallowing clicks on links inside toggles */ - var toggleLinks = toggles[i].querySelectorAll('a'); - for (var j = 0; j < toggleLinks.length; j++) { - addEventListener(toggleLinks[j], 'click', function(e) { - e.stopPropagation(); - }); - } - - /* Prevents from disallowing clicks on "copy to clipboard" elements inside toggles */ - var copyToClipboardElements = toggles[i].querySelectorAll('span[data-clipboard-text]'); - for (var k = 0; k < copyToClipboardElements.length; k++) { - addEventListener(copyToClipboardElements[k], 'click', function(e) { - e.stopPropagation(); - }); - } - toggles[i].setAttribute('data-processed', 'true'); } })(); diff --git a/lib/symfony/error-handler/Resources/bin/extract-tentative-return-types.php b/lib/symfony/error-handler/Resources/bin/extract-tentative-return-types.php old mode 100644 new mode 100755 diff --git a/lib/symfony/error-handler/Resources/bin/patch-type-declarations b/lib/symfony/error-handler/Resources/bin/patch-type-declarations old mode 100644 new mode 100755 diff --git a/lib/symfony/error-handler/Resources/views/error.html.php b/lib/symfony/error-handler/Resources/views/error.html.php index 1085a5adb..3fbf28f60 100644 --- a/lib/symfony/error-handler/Resources/views/error.html.php +++ b/lib/symfony/error-handler/Resources/views/error.html.php @@ -1,10 +1,10 @@ - - + + An Error Occurred: <?= $statusText; ?> - + diff --git a/lib/symfony/error-handler/Resources/views/exception_full.html.php b/lib/symfony/error-handler/Resources/views/exception_full.html.php index 9d5f6e336..af04db1bd 100644 --- a/lib/symfony/error-handler/Resources/views/exception_full.html.php +++ b/lib/symfony/error-handler/Resources/views/exception_full.html.php @@ -2,11 +2,11 @@ - - - + + + <?= $_message; ?> - + diff --git a/lib/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/lib/symfony/event-dispatcher-contracts/EventDispatcherInterface.php index 610d6ac06..2d7840d32 100644 --- a/lib/symfony/event-dispatcher-contracts/EventDispatcherInterface.php +++ b/lib/symfony/event-dispatcher-contracts/EventDispatcherInterface.php @@ -29,5 +29,5 @@ interface EventDispatcherInterface extends PsrEventDispatcherInterface * * @return T The passed $event MUST be returned */ - public function dispatch(object $event, string $eventName = null): object; + public function dispatch(object $event, ?string $eventName = null): object; } diff --git a/lib/symfony/event-dispatcher-contracts/composer.json b/lib/symfony/event-dispatcher-contracts/composer.json index 3618d53e9..d156b44b0 100644 --- a/lib/symfony/event-dispatcher-contracts/composer.json +++ b/lib/symfony/event-dispatcher-contracts/composer.json @@ -25,7 +25,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.6-dev" }, "thanks": { "name": "symfony/contracts", diff --git a/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php index e25a664d2..5ba83dad4 100644 --- a/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php +++ b/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php @@ -43,7 +43,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa private ?RequestStack $requestStack; private string $currentRequestHash = ''; - public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null) + public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, ?LoggerInterface $logger = null, ?RequestStack $requestStack = null) { $this->dispatcher = $dispatcher; $this->stopwatch = $stopwatch; @@ -93,7 +93,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa $this->dispatcher->removeSubscriber($subscriber); } - public function getListeners(string $eventName = null): array + public function getListeners(?string $eventName = null): array { return $this->dispatcher->getListeners($eventName); } @@ -113,12 +113,12 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa return $this->dispatcher->getListenerPriority($eventName, $listener); } - public function hasListeners(string $eventName = null): bool + public function hasListeners(?string $eventName = null): bool { return $this->dispatcher->hasListeners($eventName); } - public function dispatch(object $event, string $eventName = null): object + public function dispatch(object $event, ?string $eventName = null): object { $eventName ??= $event::class; @@ -153,7 +153,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa return $event; } - public function getCalledListeners(Request $request = null): array + public function getCalledListeners(?Request $request = null): array { if (null === $this->callStack) { return []; @@ -171,7 +171,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa return $called; } - public function getNotCalledListeners(Request $request = null): array + public function getNotCalledListeners(?Request $request = null): array { try { $allListeners = $this->dispatcher instanceof EventDispatcher ? $this->getListenersWithPriority() : $this->getListenersWithoutPriority(); @@ -213,7 +213,7 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa return $notCalled; } - public function getOrphanedEvents(Request $request = null): array + public function getOrphanedEvents(?Request $request = null): array { if ($request) { return $this->orphanedEvents[spl_object_hash($request)] ?? []; diff --git a/lib/symfony/event-dispatcher/Debug/WrappedListener.php b/lib/symfony/event-dispatcher/Debug/WrappedListener.php index 6e0de1dff..59f7c1362 100644 --- a/lib/symfony/event-dispatcher/Debug/WrappedListener.php +++ b/lib/symfony/event-dispatcher/Debug/WrappedListener.php @@ -34,7 +34,7 @@ final class WrappedListener private ?int $priority = null; private static bool $hasClassStub; - public function __construct(callable|array $listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null, int $priority = null) + public function __construct(callable|array $listener, ?string $name, Stopwatch $stopwatch, ?EventDispatcherInterface $dispatcher = null, ?int $priority = null) { $this->listener = $listener; $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? $listener(...) : null); @@ -48,7 +48,7 @@ final class WrappedListener $this->callableRef .= '::'.$listener[1]; } elseif ($listener instanceof \Closure) { $r = new \ReflectionFunction($listener); - if (str_contains($r->name, '{closure}')) { + if (str_contains($r->name, '{closure')) { $this->pretty = $this->name = 'closure'; } elseif ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { $this->name = $class->name; diff --git a/lib/symfony/event-dispatcher/EventDispatcher.php b/lib/symfony/event-dispatcher/EventDispatcher.php index 327803af6..605298926 100644 --- a/lib/symfony/event-dispatcher/EventDispatcher.php +++ b/lib/symfony/event-dispatcher/EventDispatcher.php @@ -42,7 +42,7 @@ class EventDispatcher implements EventDispatcherInterface } } - public function dispatch(object $event, string $eventName = null): object + public function dispatch(object $event, ?string $eventName = null): object { $eventName ??= $event::class; @@ -59,7 +59,7 @@ class EventDispatcher implements EventDispatcherInterface return $event; } - public function getListeners(string $eventName = null): array + public function getListeners(?string $eventName = null): array { if (null !== $eventName) { if (empty($this->listeners[$eventName])) { @@ -108,7 +108,7 @@ class EventDispatcher implements EventDispatcherInterface return null; } - public function hasListeners(string $eventName = null): bool + public function hasListeners(?string $eventName = null): bool { if (null !== $eventName) { return !empty($this->listeners[$eventName]); diff --git a/lib/symfony/event-dispatcher/EventDispatcherInterface.php b/lib/symfony/event-dispatcher/EventDispatcherInterface.php index 3cd94c938..e95a7b11d 100644 --- a/lib/symfony/event-dispatcher/EventDispatcherInterface.php +++ b/lib/symfony/event-dispatcher/EventDispatcherInterface.php @@ -59,7 +59,7 @@ interface EventDispatcherInterface extends ContractsEventDispatcherInterface * * @return array */ - public function getListeners(string $eventName = null): array; + public function getListeners(?string $eventName = null): array; /** * Gets the listener priority for a specific event. @@ -71,5 +71,5 @@ interface EventDispatcherInterface extends ContractsEventDispatcherInterface /** * Checks whether an event has any registered listeners. */ - public function hasListeners(string $eventName = null): bool; + public function hasListeners(?string $eventName = null): bool; } diff --git a/lib/symfony/event-dispatcher/ImmutableEventDispatcher.php b/lib/symfony/event-dispatcher/ImmutableEventDispatcher.php index d385d3f83..301a805cb 100644 --- a/lib/symfony/event-dispatcher/ImmutableEventDispatcher.php +++ b/lib/symfony/event-dispatcher/ImmutableEventDispatcher.php @@ -25,7 +25,7 @@ class ImmutableEventDispatcher implements EventDispatcherInterface $this->dispatcher = $dispatcher; } - public function dispatch(object $event, string $eventName = null): object + public function dispatch(object $event, ?string $eventName = null): object { return $this->dispatcher->dispatch($event, $eventName); } @@ -62,7 +62,7 @@ class ImmutableEventDispatcher implements EventDispatcherInterface throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.'); } - public function getListeners(string $eventName = null): array + public function getListeners(?string $eventName = null): array { return $this->dispatcher->getListeners($eventName); } @@ -72,7 +72,7 @@ class ImmutableEventDispatcher implements EventDispatcherInterface return $this->dispatcher->getListenerPriority($eventName, $listener); } - public function hasListeners(string $eventName = null): bool + public function hasListeners(?string $eventName = null): bool { return $this->dispatcher->hasListeners($eventName); } diff --git a/lib/symfony/filesystem/Exception/FileNotFoundException.php b/lib/symfony/filesystem/Exception/FileNotFoundException.php index 48b640809..06b732b16 100644 --- a/lib/symfony/filesystem/Exception/FileNotFoundException.php +++ b/lib/symfony/filesystem/Exception/FileNotFoundException.php @@ -19,7 +19,7 @@ namespace Symfony\Component\Filesystem\Exception; */ class FileNotFoundException extends IOException { - public function __construct(string $message = null, int $code = 0, \Throwable $previous = null, string $path = null) + public function __construct(?string $message = null, int $code = 0, ?\Throwable $previous = null, ?string $path = null) { if (null === $message) { if (null === $path) { diff --git a/lib/symfony/filesystem/Exception/IOException.php b/lib/symfony/filesystem/Exception/IOException.php index a3c544553..df3a0850a 100644 --- a/lib/symfony/filesystem/Exception/IOException.php +++ b/lib/symfony/filesystem/Exception/IOException.php @@ -22,7 +22,7 @@ class IOException extends \RuntimeException implements IOExceptionInterface { private ?string $path; - public function __construct(string $message, int $code = 0, \Throwable $previous = null, string $path = null) + public function __construct(string $message, int $code = 0, ?\Throwable $previous = null, ?string $path = null) { $this->path = $path; diff --git a/lib/symfony/filesystem/Filesystem.php b/lib/symfony/filesystem/Filesystem.php index 78458d5b9..d46aa4a42 100644 --- a/lib/symfony/filesystem/Filesystem.php +++ b/lib/symfony/filesystem/Filesystem.php @@ -46,7 +46,7 @@ class Filesystem $this->mkdir(\dirname($targetFile)); $doCopy = true; - if (!$overwriteNewerFiles && null === parse_url($originFile, \PHP_URL_HOST) && is_file($targetFile)) { + if (!$overwriteNewerFiles && !parse_url($originFile, \PHP_URL_HOST) && is_file($targetFile)) { $doCopy = filemtime($originFile) > filemtime($targetFile); } @@ -74,6 +74,9 @@ class Filesystem // Like `cp`, preserve executable permission bits self::box('chmod', $targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); + // Like `cp`, preserve the file modification time + self::box('touch', $targetFile, filemtime($originFile)); + if ($bytesCopied !== $bytesOrigin = filesize($originFile)) { throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile); } @@ -131,7 +134,7 @@ class Filesystem * * @throws IOException When touch fails */ - public function touch(string|iterable $files, int $time = null, int $atime = null) + public function touch(string|iterable $files, ?int $time = null, ?int $atime = null) { foreach ($this->toIterable($files) as $file) { if (!($time ? self::box('touch', $file, $time, $atime) : self::box('touch', $file))) { @@ -169,7 +172,7 @@ class Filesystem } } elseif (is_dir($file)) { if (!$isRecursive) { - $tmpName = \dirname(realpath($file)).'/.'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-_')); + $tmpName = \dirname(realpath($file)).'/.!'.strrev(strtr(base64_encode(random_bytes(2)), '/=', '-!')); if (file_exists($tmpName)) { try { @@ -198,7 +201,7 @@ class Filesystem throw new IOException(sprintf('Failed to remove directory "%s": ', $file).$lastError); } - } elseif (!self::box('unlink', $file) && (str_contains(self::$lastError, 'Permission denied') || file_exists($file))) { + } elseif (!self::box('unlink', $file) && ((self::$lastError && str_contains(self::$lastError, 'Permission denied')) || file_exists($file))) { throw new IOException(sprintf('Failed to remove file "%s": ', $file).self::$lastError); } } @@ -230,6 +233,10 @@ class Filesystem /** * Change the owner of an array of files or directories. * + * This method always throws on Windows, as the underlying PHP function is not supported. + * + * @see https://www.php.net/chown + * * @param string|int $user A user name or number * @param bool $recursive Whether change the owner recursively or not * @@ -258,6 +265,10 @@ class Filesystem /** * Change the group of an array of files or directories. * + * This method always throws on Windows, as the underlying PHP function is not supported. + * + * @see https://www.php.net/chgrp + * * @param string|int $group A group name or number * @param bool $recursive Whether change the group recursively or not * @@ -530,7 +541,7 @@ class Filesystem * * @throws IOException When file type is unknown */ - public function mirror(string $originDir, string $targetDir, \Traversable $iterator = null, array $options = []) + public function mirror(string $originDir, string $targetDir, ?\Traversable $iterator = null, array $options = []) { $targetDir = rtrim($targetDir, '/\\'); $originDir = rtrim($originDir, '/\\'); @@ -683,11 +694,15 @@ class Filesystem throw new IOException(sprintf('Failed to write file "%s": ', $filename).self::$lastError, 0, null, $filename); } - self::box('chmod', $tmpFile, file_exists($filename) ? fileperms($filename) : 0666 & ~umask()); + self::box('chmod', $tmpFile, self::box('fileperms', $filename) ?: 0666 & ~umask()); $this->rename($tmpFile, $filename, true); } finally { if (file_exists($tmpFile)) { + if ('\\' === \DIRECTORY_SEPARATOR && !is_writable($tmpFile)) { + self::box('chmod', $tmpFile, self::box('fileperms', $tmpFile) | 0200); + } + self::box('unlink', $tmpFile); } } diff --git a/lib/symfony/filesystem/Path.php b/lib/symfony/filesystem/Path.php index 664396235..948e1c41b 100644 --- a/lib/symfony/filesystem/Path.php +++ b/lib/symfony/filesystem/Path.php @@ -254,7 +254,7 @@ final class Path * @param string|null $extension if specified, only that extension is cut * off (may contain leading dot) */ - public static function getFilenameWithoutExtension(string $path, string $extension = null): string + public static function getFilenameWithoutExtension(string $path, ?string $extension = null): string { if ('' === $path) { return ''; @@ -365,7 +365,7 @@ final class Path } // Strip scheme - if (false !== $schemeSeparatorPosition = strpos($path, '://')) { + if (false !== ($schemeSeparatorPosition = strpos($path, '://')) && 1 !== $schemeSeparatorPosition) { $path = substr($path, $schemeSeparatorPosition + 3); } diff --git a/lib/symfony/filesystem/composer.json b/lib/symfony/filesystem/composer.json index 10a7a531c..fd75755b2 100644 --- a/lib/symfony/filesystem/composer.json +++ b/lib/symfony/filesystem/composer.json @@ -20,6 +20,9 @@ "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" + }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, "exclude-from-classmap": [ diff --git a/lib/symfony/finder/Comparator/DateComparator.php b/lib/symfony/finder/Comparator/DateComparator.php index e0c523d05..f7c27de67 100644 --- a/lib/symfony/finder/Comparator/DateComparator.php +++ b/lib/symfony/finder/Comparator/DateComparator.php @@ -36,7 +36,7 @@ class DateComparator extends Comparator throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2])); } - $operator = $matches[1] ?? '=='; + $operator = $matches[1] ?: '=='; if ('since' === $operator || 'after' === $operator) { $operator = '>'; } diff --git a/lib/symfony/finder/Iterator/RecursiveDirectoryIterator.php b/lib/symfony/finder/Iterator/RecursiveDirectoryIterator.php index 34cced688..f5fd2d4dc 100644 --- a/lib/symfony/finder/Iterator/RecursiveDirectoryIterator.php +++ b/lib/symfony/finder/Iterator/RecursiveDirectoryIterator.php @@ -63,8 +63,9 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator $subPathname .= $this->directorySeparator; } $subPathname .= $this->getFilename(); + $basePath = $this->rootPath; - if ('/' !== $basePath = $this->rootPath) { + if ('/' !== $basePath && !str_ends_with($basePath, $this->directorySeparator) && !str_ends_with($basePath, '/')) { $basePath .= $this->directorySeparator; } diff --git a/lib/symfony/finder/Iterator/VcsIgnoredFilterIterator.php b/lib/symfony/finder/Iterator/VcsIgnoredFilterIterator.php index ddd700772..b278706e9 100644 --- a/lib/symfony/finder/Iterator/VcsIgnoredFilterIterator.php +++ b/lib/symfony/finder/Iterator/VcsIgnoredFilterIterator.php @@ -37,9 +37,9 @@ final class VcsIgnoredFilterIterator extends \FilterIterator { $this->baseDir = $this->normalizePath($baseDir); - foreach ($this->parentDirectoriesUpwards($this->baseDir) as $parentDirectory) { - if (@is_dir("{$parentDirectory}/.git")) { - $this->baseDir = $parentDirectory; + foreach ([$this->baseDir, ...$this->parentDirectoriesUpwards($this->baseDir)] as $directory) { + if (@is_dir("{$directory}/.git")) { + $this->baseDir = $directory; break; } } diff --git a/lib/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php index 7498a82d1..ae27502cf 100644 --- a/lib/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php +++ b/lib/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php @@ -37,7 +37,7 @@ final class CachePoolClearerCacheWarmer implements CacheWarmerInterface $this->pools = $pools; } - public function warmUp(string $cacheDir, string $buildDir = null): array + public function warmUp(string $cacheDir, ?string $buildDir = null): array { foreach ($this->pools as $pool) { if ($this->poolClearer->hasPool($pool)) { diff --git a/lib/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php index 7e039ae2f..c43fc8af1 100644 --- a/lib/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php +++ b/lib/symfony/framework-bundle/CacheWarmer/ConfigBuilderCacheWarmer.php @@ -15,10 +15,14 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Config\Builder\ConfigBuilderGenerator; use Symfony\Component\Config\Builder\ConfigBuilderGeneratorInterface; use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; +use Symfony\Component\DependencyInjection\ParameterBag\ContainerBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; /** @@ -31,7 +35,7 @@ class ConfigBuilderCacheWarmer implements CacheWarmerInterface private KernelInterface $kernel; private ?LoggerInterface $logger; - public function __construct(KernelInterface $kernel, LoggerInterface $logger = null) + public function __construct(KernelInterface $kernel, ?LoggerInterface $logger = null) { $this->kernel = $kernel; $this->logger = $logger; @@ -50,12 +54,27 @@ class ConfigBuilderCacheWarmer implements CacheWarmerInterface $generator = new ConfigBuilderGenerator($buildDir); - foreach ($this->kernel->getBundles() as $bundle) { - $extension = $bundle->getContainerExtension(); - if (null === $extension) { - continue; - } + if ($this->kernel instanceof Kernel) { + /** @var ContainerBuilder $container */ + $container = \Closure::bind(function (Kernel $kernel) { + $containerBuilder = $kernel->getContainerBuilder(); + $kernel->prepareContainer($containerBuilder); + return $containerBuilder; + }, null, $this->kernel)($this->kernel); + + $extensions = $container->getExtensions(); + } else { + $extensions = []; + foreach ($this->kernel->getBundles() as $bundle) { + $extension = $bundle->getContainerExtension(); + if (null !== $extension) { + $extensions[] = $extension; + } + } + } + + foreach ($extensions as $extension) { try { $this->dumpExtension($extension, $generator); } catch (\Exception $e) { @@ -73,7 +92,8 @@ class ConfigBuilderCacheWarmer implements CacheWarmerInterface if ($extension instanceof ConfigurationInterface) { $configuration = $extension; } elseif ($extension instanceof ConfigurationExtensionInterface) { - $configuration = $extension->getConfiguration([], new ContainerBuilder($this->kernel->getContainer()->getParameterBag())); + $container = $this->kernel->getContainer(); + $configuration = $extension->getConfiguration([], new ContainerBuilder($container instanceof Container ? new ContainerBag($container) : new ParameterBag())); } if (!$configuration) { @@ -85,6 +105,6 @@ class ConfigBuilderCacheWarmer implements CacheWarmerInterface public function isOptional(): bool { - return true; + return false; } } diff --git a/lib/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php b/lib/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php index 2af9a2fe8..c2b9478a3 100644 --- a/lib/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php +++ b/lib/symfony/framework-bundle/CacheWarmer/RouterCacheWarmer.php @@ -34,7 +34,7 @@ class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterf $this->container = $container; } - public function warmUp(string $cacheDir, string $buildDir = null): array + public function warmUp(string $cacheDir, ?string $buildDir = null): array { $router = $this->container->get('router'); diff --git a/lib/symfony/framework-bundle/Command/CacheClearCommand.php b/lib/symfony/framework-bundle/Command/CacheClearCommand.php index 878157e87..eeafd1bd3 100644 --- a/lib/symfony/framework-bundle/Command/CacheClearCommand.php +++ b/lib/symfony/framework-bundle/Command/CacheClearCommand.php @@ -40,7 +40,7 @@ class CacheClearCommand extends Command private CacheClearerInterface $cacheClearer; private Filesystem $filesystem; - public function __construct(CacheClearerInterface $cacheClearer, Filesystem $filesystem = null) + public function __construct(CacheClearerInterface $cacheClearer, ?Filesystem $filesystem = null) { parent::__construct(); @@ -146,6 +146,16 @@ EOF } $this->warmupOptionals($useBuildDir ? $realCacheDir : $warmupDir, $warmupDir, $io); } + + // fix references to cached files with the real cache directory name + $search = [$warmupDir, str_replace('/', '\\/', $warmupDir), str_replace('\\', '\\\\', $warmupDir)]; + $replace = str_replace('\\', '/', $realBuildDir); + foreach (Finder::create()->files()->in($warmupDir) as $file) { + $content = str_replace($search, $replace, file_get_contents($file), $count); + if ($count) { + file_put_contents($file, $content); + } + } } if (!$fs->exists($warmupDir.'/'.$containerDir)) { @@ -154,7 +164,7 @@ EOF } if ($this->isNfs($realBuildDir)) { - $io->note('For better performances, you should move the cache and log directories to a non-shared folder of the VM.'); + $io->note('For better performance, you should move the cache and log directories to a non-shared folder of the VM.'); $fs->remove($realBuildDir); } else { $fs->rename($realBuildDir, $oldBuildDir); @@ -200,7 +210,7 @@ EOF if (null === $mounts) { $mounts = []; - if ('/' === \DIRECTORY_SEPARATOR && $files = @file('/proc/mounts')) { + if ('/' === \DIRECTORY_SEPARATOR && @is_readable('/proc/mounts') && $files = @file('/proc/mounts')) { foreach ($files as $mount) { $mount = \array_slice(explode(' ', $mount), 1, -3); if (!\in_array(array_pop($mount), ['vboxsf', 'nfs'])) { @@ -227,16 +237,6 @@ EOF throw new \LogicException('Calling "cache:clear" with a kernel that does not implement "Symfony\Component\HttpKernel\RebootableInterface" is not supported.'); } $kernel->reboot($warmupDir); - - // fix references to cached files with the real cache directory name - $search = [$warmupDir, str_replace('\\', '\\\\', $warmupDir)]; - $replace = str_replace('\\', '/', $realBuildDir); - foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file), $count); - if ($count) { - file_put_contents($file, $content); - } - } } private function warmupOptionals(string $cacheDir, string $warmupDir, SymfonyStyle $io): void diff --git a/lib/symfony/framework-bundle/Command/CachePoolClearCommand.php b/lib/symfony/framework-bundle/Command/CachePoolClearCommand.php index fcd70ca0e..8b8b9cd35 100644 --- a/lib/symfony/framework-bundle/Command/CachePoolClearCommand.php +++ b/lib/symfony/framework-bundle/Command/CachePoolClearCommand.php @@ -38,7 +38,7 @@ final class CachePoolClearCommand extends Command /** * @param string[]|null $poolNames */ - public function __construct(Psr6CacheClearer $poolClearer, array $poolNames = null) + public function __construct(Psr6CacheClearer $poolClearer, ?array $poolNames = null) { parent::__construct(); @@ -72,7 +72,7 @@ EOF $poolNames = $input->getArgument('pools'); $excludedPoolNames = $input->getOption('exclude'); - if ($input->getOption('all')) { + if ($clearAll = $input->getOption('all')) { if (!$this->poolNames) { throw new InvalidArgumentException('Could not clear all cache pools, try specifying a specific pool or cache clearer.'); } @@ -91,7 +91,7 @@ EOF foreach ($poolNames as $id) { if ($this->poolClearer->hasPool($id)) { $pools[$id] = $id; - } else { + } elseif (!$clearAll || $kernel->getContainer()->has($id)) { $pool = $kernel->getContainer()->get($id); if ($pool instanceof CacheItemPoolInterface) { diff --git a/lib/symfony/framework-bundle/Command/CachePoolDeleteCommand.php b/lib/symfony/framework-bundle/Command/CachePoolDeleteCommand.php index 7b53ceb8b..dfa307bc0 100644 --- a/lib/symfony/framework-bundle/Command/CachePoolDeleteCommand.php +++ b/lib/symfony/framework-bundle/Command/CachePoolDeleteCommand.php @@ -35,7 +35,7 @@ final class CachePoolDeleteCommand extends Command /** * @param string[]|null $poolNames */ - public function __construct(Psr6CacheClearer $poolClearer, array $poolNames = null) + public function __construct(Psr6CacheClearer $poolClearer, ?array $poolNames = null) { parent::__construct(); diff --git a/lib/symfony/framework-bundle/Command/ContainerDebugCommand.php b/lib/symfony/framework-bundle/Command/ContainerDebugCommand.php index df6aef5dd..3000da51a 100644 --- a/lib/symfony/framework-bundle/Command/ContainerDebugCommand.php +++ b/lib/symfony/framework-bundle/Command/ContainerDebugCommand.php @@ -284,7 +284,9 @@ EOF return $matchingServices[0]; } - return $io->choice('Select one of the following services to display its information', $matchingServices); + natsort($matchingServices); + + return $io->choice('Select one of the following services to display its information', array_values($matchingServices)); } private function findProperTagName(InputInterface $input, SymfonyStyle $io, ContainerBuilder $container, string $tagName): string @@ -302,7 +304,9 @@ EOF return $matchingTags[0]; } - return $io->choice('Select one of the following tags to display its information', $matchingTags); + natsort($matchingTags); + + return $io->choice('Select one of the following tags to display its information', array_values($matchingTags)); } private function findServiceIdsContaining(ContainerBuilder $container, string $name, bool $showHidden): array diff --git a/lib/symfony/framework-bundle/Command/DebugAutowiringCommand.php b/lib/symfony/framework-bundle/Command/DebugAutowiringCommand.php index ab4793b68..f6efd8bef 100644 --- a/lib/symfony/framework-bundle/Command/DebugAutowiringCommand.php +++ b/lib/symfony/framework-bundle/Command/DebugAutowiringCommand.php @@ -35,7 +35,7 @@ class DebugAutowiringCommand extends ContainerDebugCommand { private ?FileLinkFormatter $fileLinkFormatter; - public function __construct(string $name = null, FileLinkFormatter $fileLinkFormatter = null) + public function __construct(?string $name = null, ?FileLinkFormatter $fileLinkFormatter = null) { $this->fileLinkFormatter = $fileLinkFormatter; parent::__construct($name); diff --git a/lib/symfony/framework-bundle/Command/RouterDebugCommand.php b/lib/symfony/framework-bundle/Command/RouterDebugCommand.php index 8d4e38a29..9318b46be 100644 --- a/lib/symfony/framework-bundle/Command/RouterDebugCommand.php +++ b/lib/symfony/framework-bundle/Command/RouterDebugCommand.php @@ -42,7 +42,7 @@ class RouterDebugCommand extends Command private RouterInterface $router; private ?FileLinkFormatter $fileLinkFormatter; - public function __construct(RouterInterface $router, FileLinkFormatter $fileLinkFormatter = null) + public function __construct(RouterInterface $router, ?FileLinkFormatter $fileLinkFormatter = null) { parent::__construct(); diff --git a/lib/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php b/lib/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php index 22be89502..5945c16cc 100644 --- a/lib/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php +++ b/lib/symfony/framework-bundle/Command/SecretsDecryptToLocalCommand.php @@ -31,7 +31,7 @@ final class SecretsDecryptToLocalCommand extends Command private AbstractVault $vault; private ?AbstractVault $localVault; - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) { $this->vault = $vault; $this->localVault = $localVault; @@ -48,7 +48,7 @@ The %command.name% command decrypts all secrets and copies them in %command.full_name% -When the option --force is provided, secrets that already exist in the local vault are overriden. +When the --force option is provided, secrets that already exist in the local vault are overridden. %command.full_name% --force EOF diff --git a/lib/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php b/lib/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php index 4c613ef7b..46e0baffc 100644 --- a/lib/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php +++ b/lib/symfony/framework-bundle/Command/SecretsEncryptFromLocalCommand.php @@ -30,7 +30,7 @@ final class SecretsEncryptFromLocalCommand extends Command private AbstractVault $vault; private ?AbstractVault $localVault; - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) { $this->vault = $vault; $this->localVault = $localVault; diff --git a/lib/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php b/lib/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php index 761f6c260..989eff9fd 100644 --- a/lib/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php +++ b/lib/symfony/framework-bundle/Command/SecretsGenerateKeysCommand.php @@ -33,7 +33,7 @@ final class SecretsGenerateKeysCommand extends Command private AbstractVault $vault; private ?AbstractVault $localVault; - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) { $this->vault = $vault; $this->localVault = $localVault; diff --git a/lib/symfony/framework-bundle/Command/SecretsListCommand.php b/lib/symfony/framework-bundle/Command/SecretsListCommand.php index de8a7e772..9a24f4a90 100644 --- a/lib/symfony/framework-bundle/Command/SecretsListCommand.php +++ b/lib/symfony/framework-bundle/Command/SecretsListCommand.php @@ -34,7 +34,7 @@ final class SecretsListCommand extends Command private AbstractVault $vault; private ?AbstractVault $localVault; - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) { $this->vault = $vault; $this->localVault = $localVault; diff --git a/lib/symfony/framework-bundle/Command/SecretsRemoveCommand.php b/lib/symfony/framework-bundle/Command/SecretsRemoveCommand.php index e03afcd0c..1789f2981 100644 --- a/lib/symfony/framework-bundle/Command/SecretsRemoveCommand.php +++ b/lib/symfony/framework-bundle/Command/SecretsRemoveCommand.php @@ -35,7 +35,7 @@ final class SecretsRemoveCommand extends Command private AbstractVault $vault; private ?AbstractVault $localVault; - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) { $this->vault = $vault; $this->localVault = $localVault; diff --git a/lib/symfony/framework-bundle/Command/SecretsSetCommand.php b/lib/symfony/framework-bundle/Command/SecretsSetCommand.php index 0e831a343..2d2b8c5cb 100644 --- a/lib/symfony/framework-bundle/Command/SecretsSetCommand.php +++ b/lib/symfony/framework-bundle/Command/SecretsSetCommand.php @@ -36,7 +36,7 @@ final class SecretsSetCommand extends Command private AbstractVault $vault; private ?AbstractVault $localVault; - public function __construct(AbstractVault $vault, AbstractVault $localVault = null) + public function __construct(AbstractVault $vault, ?AbstractVault $localVault = null) { $this->vault = $vault; $this->localVault = $localVault; diff --git a/lib/symfony/framework-bundle/Command/TranslationDebugCommand.php b/lib/symfony/framework-bundle/Command/TranslationDebugCommand.php index 79a67847a..53ee1949f 100644 --- a/lib/symfony/framework-bundle/Command/TranslationDebugCommand.php +++ b/lib/symfony/framework-bundle/Command/TranslationDebugCommand.php @@ -59,7 +59,7 @@ class TranslationDebugCommand extends Command private array $codePaths; private array $enabledLocales; - public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = []) + public function __construct(TranslatorInterface $translator, TranslationReaderInterface $reader, ExtractorInterface $extractor, ?string $defaultTransPath = null, ?string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = []) { parent::__construct(); @@ -79,7 +79,7 @@ class TranslationDebugCommand extends Command ->setDefinition([ new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), - new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'The messages domain'), + new InputOption('domain', null, InputOption::VALUE_REQUIRED, 'The messages domain'), new InputOption('only-missing', null, InputOption::VALUE_NONE, 'Display only missing messages'), new InputOption('only-unused', null, InputOption::VALUE_NONE, 'Display only unused messages'), new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'), diff --git a/lib/symfony/framework-bundle/Command/TranslationUpdateCommand.php b/lib/symfony/framework-bundle/Command/TranslationUpdateCommand.php index 4563779ba..259027ce0 100644 --- a/lib/symfony/framework-bundle/Command/TranslationUpdateCommand.php +++ b/lib/symfony/framework-bundle/Command/TranslationUpdateCommand.php @@ -19,7 +19,6 @@ use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\HttpKernel\KernelInterface; @@ -60,10 +59,14 @@ class TranslationUpdateCommand extends Command private array $codePaths; private array $enabledLocales; - public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, string $defaultTransPath = null, string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = []) + public function __construct(TranslationWriterInterface $writer, TranslationReaderInterface $reader, ExtractorInterface $extractor, string $defaultLocale, ?string $defaultTransPath = null, ?string $defaultViewsPath = null, array $transPaths = [], array $codePaths = [], array $enabledLocales = []) { parent::__construct(); + if (!method_exists($writer, 'getFormats')) { + throw new \InvalidArgumentException(sprintf('The writer class "%s" does not implement the "getFormats()" method.', $writer::class)); + } + $this->writer = $writer; $this->reader = $reader; $this->extractor = $extractor; @@ -81,14 +84,14 @@ class TranslationUpdateCommand extends Command ->setDefinition([ new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages'), - new InputOption('prefix', null, InputOption::VALUE_OPTIONAL, 'Override the default prefix', '__'), - new InputOption('format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'xlf12'), + new InputOption('prefix', null, InputOption::VALUE_REQUIRED, 'Override the default prefix', '__'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'Override the default output format', 'xlf12'), new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), new InputOption('force', null, InputOption::VALUE_NONE, 'Should the extract be done'), new InputOption('clean', null, InputOption::VALUE_NONE, 'Should clean not found messages'), - new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'Specify the domain to extract'), + new InputOption('domain', null, InputOption::VALUE_REQUIRED, 'Specify the domain to extract'), new InputOption('sort', null, InputOption::VALUE_OPTIONAL, 'Return list of messages sorted alphabetically (only works with --dump-messages)', 'asc'), - new InputOption('as-tree', null, InputOption::VALUE_OPTIONAL, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), + new InputOption('as-tree', null, InputOption::VALUE_REQUIRED, 'Dump the messages as a tree-like structure: The given value defines the level where to switch to inline YAML'), ]) ->setHelp(<<<'EOF' The %command.name% command extracts translation strings from templates @@ -124,13 +127,6 @@ EOF protected function execute(InputInterface $input, OutputInterface $output): int { - $io = new SymfonyStyle($input, $output); - $errorIo = $output instanceof ConsoleOutputInterface ? new SymfonyStyle($input, $output->getErrorOutput()) : $io; - - if ('translation:update' === $input->getFirstArgument()) { - $errorIo->caution('Command "translation:update" is deprecated since version 5.4 and will be removed in Symfony 6.0. Use "translation:extract" instead.'); - } - $io = new SymfonyStyle($input, $output); $errorIo = $io->getErrorStyle(); diff --git a/lib/symfony/framework-bundle/Console/Application.php b/lib/symfony/framework-bundle/Console/Application.php index 38dd8405a..b46dc0dee 100644 --- a/lib/symfony/framework-bundle/Console/Application.php +++ b/lib/symfony/framework-bundle/Console/Application.php @@ -157,7 +157,7 @@ class Application extends BaseApplication return $command; } - public function all(string $namespace = null): array + public function all(?string $namespace = null): array { $this->registerCommands(); diff --git a/lib/symfony/framework-bundle/Console/Descriptor/Descriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/Descriptor.php index ba500adb2..8541f71bb 100644 --- a/lib/symfony/framework-bundle/Console/Descriptor/Descriptor.php +++ b/lib/symfony/framework-bundle/Console/Descriptor/Descriptor.php @@ -96,7 +96,7 @@ abstract class Descriptor implements DescriptorInterface * * @param Definition|Alias|object $service */ - abstract protected function describeContainerService(object $service, array $options = [], ContainerBuilder $container = null): void; + abstract protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void; /** * Describes container services. @@ -108,9 +108,9 @@ abstract class Descriptor implements DescriptorInterface abstract protected function describeContainerDeprecations(ContainerBuilder $container, array $options = []): void; - abstract protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $container = null): void; + abstract protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void; - abstract protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $container = null): void; + abstract protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void; abstract protected function describeContainerParameter(mixed $parameter, ?array $deprecation, array $options = []): void; @@ -278,7 +278,7 @@ abstract class Descriptor implements DescriptorInterface return $reverseAliases; } - public static function getClassDescription(string $class, string &$resolvedClass = null): string + public static function getClassDescription(string $class, ?string &$resolvedClass = null): string { $resolvedClass = $class; try { diff --git a/lib/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php index 1dc567a3f..28260ad86 100644 --- a/lib/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php +++ b/lib/symfony/framework-bundle/Console/Descriptor/JsonDescriptor.php @@ -70,7 +70,7 @@ class JsonDescriptor extends Descriptor $this->writeData($data, $options); } - protected function describeContainerService(object $service, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void { if (!isset($options['id'])) { throw new \InvalidArgumentException('An "id" option must be provided.'); @@ -121,12 +121,12 @@ class JsonDescriptor extends Descriptor $this->writeData($data, $options); } - protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void { $this->writeData($this->getContainerDefinitionData($definition, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $container, $options['id'] ?? null), $options); } - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void { if (!$container) { $this->writeData($this->getContainerAliasData($alias), $options); @@ -245,7 +245,7 @@ class JsonDescriptor extends Descriptor return $sortedParameters; } - private function getContainerDefinitionData(Definition $definition, bool $omitTags = false, bool $showArguments = false, ContainerBuilder $container = null, string $id = null): array + private function getContainerDefinitionData(Definition $definition, bool $omitTags = false, bool $showArguments = false, ?ContainerBuilder $container = null, ?string $id = null): array { $data = [ 'class' => (string) $definition->getClass(), @@ -393,7 +393,7 @@ class JsonDescriptor extends Descriptor $data['type'] = 'closure'; $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { + if (str_contains($r->name, '{closure')) { return $data; } $data['name'] = $r->name; @@ -418,7 +418,7 @@ class JsonDescriptor extends Descriptor throw new \InvalidArgumentException('Callable is not describable.'); } - private function describeValue($value, bool $omitTags, bool $showArguments, ContainerBuilder $container = null, string $id = null): mixed + private function describeValue($value, bool $omitTags, bool $showArguments, ?ContainerBuilder $container = null, ?string $id = null): mixed { if (\is_array($value)) { $data = []; diff --git a/lib/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php index 275294d7e..b4192ed6a 100644 --- a/lib/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php +++ b/lib/symfony/framework-bundle/Console/Descriptor/MarkdownDescriptor.php @@ -98,7 +98,7 @@ class MarkdownDescriptor extends Descriptor } } - protected function describeContainerService(object $service, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void { if (!isset($options['id'])) { throw new \InvalidArgumentException('An "id" option must be provided.'); @@ -206,7 +206,7 @@ class MarkdownDescriptor extends Descriptor } } - protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void { $output = ''; @@ -276,7 +276,7 @@ class MarkdownDescriptor extends Descriptor $this->write(isset($options['id']) ? sprintf("### %s\n\n%s\n", $options['id'], $output) : $output); } - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void { $output = '- Service: `'.$alias.'`' ."\n".'- Public: '.($alias->isPublic() && !$alias->isPrivate() ? 'yes' : 'no'); @@ -403,7 +403,7 @@ class MarkdownDescriptor extends Descriptor $string .= "\n- Type: `closure`"; $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { + if (str_contains($r->name, '{closure')) { $this->write($string."\n"); return; diff --git a/lib/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php index b0fe7f2ac..f8d0133e5 100644 --- a/lib/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php +++ b/lib/symfony/framework-bundle/Console/Descriptor/TextDescriptor.php @@ -40,7 +40,7 @@ class TextDescriptor extends Descriptor { private ?FileLinkFormatter $fileLinkFormatter; - public function __construct(FileLinkFormatter $fileLinkFormatter = null) + public function __construct(?FileLinkFormatter $fileLinkFormatter = null) { $this->fileLinkFormatter = $fileLinkFormatter; } @@ -159,7 +159,7 @@ class TextDescriptor extends Descriptor } } - protected function describeContainerService(object $service, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void { if (!isset($options['id'])) { throw new \InvalidArgumentException('An "id" option must be provided.'); @@ -281,7 +281,7 @@ class TextDescriptor extends Descriptor $options['output']->table($tableHeaders, $tableRows); } - protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void { if (isset($options['id'])) { $options['output']->title(sprintf('Information for Service "%s"', $options['id'])); @@ -420,7 +420,7 @@ class TextDescriptor extends Descriptor $options['output']->listing($formattedLogs); } - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void { if ($alias->isPublic() && !$alias->isPrivate()) { $options['output']->comment(sprintf('This service is a public alias for the service %s', (string) $alias)); @@ -579,7 +579,7 @@ class TextDescriptor extends Descriptor return trim($configAsString); } - private function formatControllerLink(mixed $controller, string $anchorText, callable $getContainer = null): string + private function formatControllerLink(mixed $controller, string $anchorText, ?callable $getContainer = null): string { if (null === $this->fileLinkFormatter) { return $anchorText; @@ -597,7 +597,7 @@ class TextDescriptor extends Descriptor } elseif (!\is_string($controller)) { return $anchorText; } elseif (str_contains($controller, '::')) { - $r = new \ReflectionMethod($controller); + $r = new \ReflectionMethod(...explode('::', $controller, 2)); } else { $r = new \ReflectionFunction($controller); } @@ -649,7 +649,7 @@ class TextDescriptor extends Descriptor if ($callable instanceof \Closure) { $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { + if (str_contains($r->name, '{closure')) { return 'Closure()'; } if ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { diff --git a/lib/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php b/lib/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php index f12e4583b..e5c912ce4 100644 --- a/lib/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php +++ b/lib/symfony/framework-bundle/Console/Descriptor/XmlDescriptor.php @@ -53,7 +53,7 @@ class XmlDescriptor extends Descriptor $this->writeDocument($this->getContainerTagsDocument($container, isset($options['show_hidden']) && $options['show_hidden'])); } - protected function describeContainerService(object $service, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerService(object $service, array $options = [], ?ContainerBuilder $container = null): void { if (!isset($options['id'])) { throw new \InvalidArgumentException('An "id" option must be provided.'); @@ -67,12 +67,12 @@ class XmlDescriptor extends Descriptor $this->writeDocument($this->getContainerServicesDocument($container, $options['tag'] ?? null, isset($options['show_hidden']) && $options['show_hidden'], isset($options['show_arguments']) && $options['show_arguments'], $options['filter'] ?? null, $options['id'] ?? null)); } - protected function describeContainerDefinition(Definition $definition, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerDefinition(Definition $definition, array $options = [], ?ContainerBuilder $container = null): void { $this->writeDocument($this->getContainerDefinitionDocument($definition, $options['id'] ?? null, isset($options['omit_tags']) && $options['omit_tags'], isset($options['show_arguments']) && $options['show_arguments'], $container)); } - protected function describeContainerAlias(Alias $alias, array $options = [], ContainerBuilder $container = null): void + protected function describeContainerAlias(Alias $alias, array $options = [], ?ContainerBuilder $container = null): void { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($dom->importNode($this->getContainerAliasDocument($alias, $options['id'] ?? null)->childNodes->item(0), true)); @@ -162,7 +162,7 @@ class XmlDescriptor extends Descriptor return $dom; } - private function getRouteDocument(Route $route, string $name = null): \DOMDocument + private function getRouteDocument(Route $route, ?string $name = null): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($routeXML = $dom->createElement('route')); @@ -268,7 +268,7 @@ class XmlDescriptor extends Descriptor return $dom; } - private function getContainerServiceDocument(object $service, string $id, ContainerBuilder $container = null, bool $showArguments = false): \DOMDocument + private function getContainerServiceDocument(object $service, string $id, ?ContainerBuilder $container = null, bool $showArguments = false): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); @@ -288,7 +288,7 @@ class XmlDescriptor extends Descriptor return $dom; } - private function getContainerServicesDocument(ContainerBuilder $container, string $tag = null, bool $showHidden = false, bool $showArguments = false, callable $filter = null, string $id = null): \DOMDocument + private function getContainerServicesDocument(ContainerBuilder $container, ?string $tag = null, bool $showHidden = false, bool $showArguments = false, ?callable $filter = null, ?string $id = null): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($containerXML = $dom->createElement('container')); @@ -318,7 +318,7 @@ class XmlDescriptor extends Descriptor return $dom; } - private function getContainerDefinitionDocument(Definition $definition, string $id = null, bool $omitTags = false, bool $showArguments = false, ContainerBuilder $container = null): \DOMDocument + private function getContainerDefinitionDocument(Definition $definition, ?string $id = null, bool $omitTags = false, bool $showArguments = false, ?ContainerBuilder $container = null): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($serviceXML = $dom->createElement('definition')); @@ -418,7 +418,7 @@ class XmlDescriptor extends Descriptor /** * @return \DOMNode[] */ - private function getArgumentNodes(array $arguments, \DOMDocument $dom, ContainerBuilder $container = null): array + private function getArgumentNodes(array $arguments, \DOMDocument $dom, ?ContainerBuilder $container = null): array { $nodes = []; @@ -466,7 +466,7 @@ class XmlDescriptor extends Descriptor return $nodes; } - private function getContainerAliasDocument(Alias $alias, string $id = null): \DOMDocument + private function getContainerAliasDocument(Alias $alias, ?string $id = null): \DOMDocument { $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($aliasXML = $dom->createElement('alias')); @@ -581,7 +581,7 @@ class XmlDescriptor extends Descriptor $callableXML->setAttribute('type', 'closure'); $r = new \ReflectionFunction($callable); - if (str_contains($r->name, '{closure}')) { + if (str_contains($r->name, '{closure')) { return $dom; } $callableXML->setAttribute('name', $r->name); diff --git a/lib/symfony/framework-bundle/Console/Helper/DescriptorHelper.php b/lib/symfony/framework-bundle/Console/Helper/DescriptorHelper.php index 47d69fef4..b12a8d862 100644 --- a/lib/symfony/framework-bundle/Console/Helper/DescriptorHelper.php +++ b/lib/symfony/framework-bundle/Console/Helper/DescriptorHelper.php @@ -25,7 +25,7 @@ use Symfony\Component\ErrorHandler\ErrorRenderer\FileLinkFormatter; */ class DescriptorHelper extends BaseDescriptorHelper { - public function __construct(FileLinkFormatter $fileLinkFormatter = null) + public function __construct(?FileLinkFormatter $fileLinkFormatter = null) { $this ->register('txt', new TextDescriptor($fileLinkFormatter)) diff --git a/lib/symfony/framework-bundle/Controller/AbstractController.php b/lib/symfony/framework-bundle/Controller/AbstractController.php index 4ede883f7..6da5b1d54 100644 --- a/lib/symfony/framework-bundle/Controller/AbstractController.php +++ b/lib/symfony/framework-bundle/Controller/AbstractController.php @@ -163,7 +163,7 @@ abstract class AbstractController implements ServiceSubscriberInterface /** * Returns a BinaryFileResponse object with original or customized file name and disposition header. */ - protected function file(\SplFileInfo|string $file, string $fileName = null, string $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT): BinaryFileResponse + protected function file(\SplFileInfo|string $file, ?string $fileName = null, string $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT): BinaryFileResponse { $response = new BinaryFileResponse($file); $response->setContentDisposition($disposition, $fileName ?? $response->getFile()->getFilename()); @@ -248,7 +248,7 @@ abstract class AbstractController implements ServiceSubscriberInterface * If an invalid form is found in the list of parameters, a 422 status code is returned. * Forms found in parameters are auto-cast to form views. */ - protected function render(string $view, array $parameters = [], Response $response = null): Response + protected function render(string $view, array $parameters = [], ?Response $response = null): Response { return $this->doRender($view, null, $parameters, $response, __FUNCTION__); } @@ -259,7 +259,7 @@ abstract class AbstractController implements ServiceSubscriberInterface * If an invalid form is found in the list of parameters, a 422 status code is returned. * Forms found in parameters are auto-cast to form views. */ - protected function renderBlock(string $view, string $block, array $parameters = [], Response $response = null): Response + protected function renderBlock(string $view, string $block, array $parameters = [], ?Response $response = null): Response { return $this->doRender($view, $block, $parameters, $response, __FUNCTION__); } @@ -271,7 +271,7 @@ abstract class AbstractController implements ServiceSubscriberInterface * * @deprecated since Symfony 6.2, use render() instead */ - protected function renderForm(string $view, array $parameters = [], Response $response = null): Response + protected function renderForm(string $view, array $parameters = [], ?Response $response = null): Response { trigger_deprecation('symfony/framework-bundle', '6.2', 'The "%s::renderForm()" method is deprecated, use "render()" instead.', get_debug_type($this)); @@ -281,7 +281,7 @@ abstract class AbstractController implements ServiceSubscriberInterface /** * Streams a view. */ - protected function stream(string $view, array $parameters = [], StreamedResponse $response = null): StreamedResponse + protected function stream(string $view, array $parameters = [], ?StreamedResponse $response = null): StreamedResponse { if (!$this->container->has('twig')) { throw new \LogicException('You cannot use the "stream" method if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); @@ -309,7 +309,7 @@ abstract class AbstractController implements ServiceSubscriberInterface * * throw $this->createNotFoundException('Page not found!'); */ - protected function createNotFoundException(string $message = 'Not Found', \Throwable $previous = null): NotFoundHttpException + protected function createNotFoundException(string $message = 'Not Found', ?\Throwable $previous = null): NotFoundHttpException { return new NotFoundHttpException($message, $previous); } @@ -323,7 +323,7 @@ abstract class AbstractController implements ServiceSubscriberInterface * * @throws \LogicException If the Security component is not available */ - protected function createAccessDeniedException(string $message = 'Access Denied.', \Throwable $previous = null): AccessDeniedException + protected function createAccessDeniedException(string $message = 'Access Denied.', ?\Throwable $previous = null): AccessDeniedException { if (!class_exists(AccessDeniedException::class)) { throw new \LogicException('You cannot use the "createAccessDeniedException" method if the Security component is not available. Try running "composer require symfony/security-bundle".'); @@ -406,7 +406,7 @@ abstract class AbstractController implements ServiceSubscriberInterface /** * @param LinkInterface[] $links */ - protected function sendEarlyHints(iterable $links = [], Response $response = null): Response + protected function sendEarlyHints(iterable $links = [], ?Response $response = null): Response { if (!$this->container->has('web_link.http_header_serializer')) { throw new \LogicException('You cannot use the "sendEarlyHints" method if the WebLink component is not available. Try running "composer require symfony/web-link".'); diff --git a/lib/symfony/framework-bundle/Controller/RedirectController.php b/lib/symfony/framework-bundle/Controller/RedirectController.php index f5f42a7f7..24e1dad85 100644 --- a/lib/symfony/framework-bundle/Controller/RedirectController.php +++ b/lib/symfony/framework-bundle/Controller/RedirectController.php @@ -31,7 +31,7 @@ class RedirectController private ?int $httpPort; private ?int $httpsPort; - public function __construct(UrlGeneratorInterface $router = null, int $httpPort = null, int $httpsPort = null) + public function __construct(?UrlGeneratorInterface $router = null, ?int $httpPort = null, ?int $httpsPort = null) { $this->router = $router; $this->httpPort = $httpPort; @@ -107,9 +107,9 @@ class RedirectController * * @throws HttpException In case the path is empty */ - public function urlRedirectAction(Request $request, string $path, bool $permanent = false, string $scheme = null, int $httpPort = null, int $httpsPort = null, bool $keepRequestMethod = false): Response + public function urlRedirectAction(Request $request, string $path, bool $permanent = false, ?string $scheme = null, ?int $httpPort = null, ?int $httpsPort = null, bool $keepRequestMethod = false): Response { - if ('' == $path) { + if ('' === $path) { throw new HttpException($permanent ? 410 : 404); } @@ -119,13 +119,17 @@ class RedirectController $statusCode = $permanent ? 301 : 302; } + $scheme ??= $request->getScheme(); + + if (str_starts_with($path, '//')) { + $path = $scheme.':'.$path; + } + // redirect if the path is a full URL if (parse_url($path, \PHP_URL_SCHEME)) { return new RedirectResponse($path, $statusCode); } - $scheme ??= $request->getScheme(); - if ($qs = $request->server->get('QUERY_STRING') ?: $request->getQueryString()) { if (!str_contains($path, '?')) { $qs = '?'.$qs; diff --git a/lib/symfony/framework-bundle/Controller/TemplateController.php b/lib/symfony/framework-bundle/Controller/TemplateController.php index 437458a49..97631572c 100644 --- a/lib/symfony/framework-bundle/Controller/TemplateController.php +++ b/lib/symfony/framework-bundle/Controller/TemplateController.php @@ -25,7 +25,7 @@ class TemplateController { private ?Environment $twig; - public function __construct(Environment $twig = null) + public function __construct(?Environment $twig = null) { $this->twig = $twig; } @@ -40,7 +40,7 @@ class TemplateController * @param array $context The context (arguments) of the template * @param int $statusCode The HTTP status code to return with the response (200 "OK" by default) */ - public function templateAction(string $template, int $maxAge = null, int $sharedAge = null, bool $private = null, array $context = [], int $statusCode = 200): Response + public function templateAction(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200): Response { if (null === $this->twig) { throw new \LogicException('You cannot use the TemplateController if the Twig Bundle is not available. Try running "composer require symfony/twig-bundle".'); @@ -68,7 +68,7 @@ class TemplateController /** * @param int $statusCode The HTTP status code (200 "OK" by default) */ - public function __invoke(string $template, int $maxAge = null, int $sharedAge = null, bool $private = null, array $context = [], int $statusCode = 200): Response + public function __invoke(string $template, ?int $maxAge = null, ?int $sharedAge = null, ?bool $private = null, array $context = [], int $statusCode = 200): Response { return $this->templateAction($template, $maxAge, $sharedAge, $private, $context, $statusCode); } diff --git a/lib/symfony/framework-bundle/DataCollector/RouterDataCollector.php b/lib/symfony/framework-bundle/DataCollector/RouterDataCollector.php index 700d0f22d..e383d48ae 100644 --- a/lib/symfony/framework-bundle/DataCollector/RouterDataCollector.php +++ b/lib/symfony/framework-bundle/DataCollector/RouterDataCollector.php @@ -28,7 +28,7 @@ class RouterDataCollector extends BaseRouterDataCollector $controller = $controller[0]; } - if ($controller instanceof RedirectController) { + if ($controller instanceof RedirectController && $request->attributes->has('_route')) { return $request->attributes->get('_route'); } diff --git a/lib/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php b/lib/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php new file mode 100644 index 000000000..7542191d0 --- /dev/null +++ b/lib/symfony/framework-bundle/DependencyInjection/Compiler/TranslationUpdateCommandPass.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class TranslationUpdateCommandPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container): void + { + if (!$container->hasDefinition('console.command.translation_extract')) { + return; + } + + $translationWriterClass = $container->getParameterBag()->resolveValue($container->findDefinition('translation.writer')->getClass()); + + if (!method_exists($translationWriterClass, 'getFormats')) { + $container->removeDefinition('console.command.translation_extract'); + } + } +} diff --git a/lib/symfony/framework-bundle/DependencyInjection/Configuration.php b/lib/symfony/framework-bundle/DependencyInjection/Configuration.php index 46177a09e..6bed89cf1 100644 --- a/lib/symfony/framework-bundle/DependencyInjection/Configuration.php +++ b/lib/symfony/framework-bundle/DependencyInjection/Configuration.php @@ -45,6 +45,7 @@ use Symfony\Component\Serializer\Encoder\JsonDecode; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Translation\Translator; use Symfony\Component\Uid\Factory\UuidFactory; +use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Validation; use Symfony\Component\Webhook\Controller\WebhookController; use Symfony\Component\WebLink\HttpHeaderSerializer; @@ -146,7 +147,7 @@ class Configuration implements ConfigurationInterface ->end() ; - $willBeAvailable = static function (string $package, string $class, string $parentPackage = null) { + $willBeAvailable = static function (string $package, string $class, ?string $parentPackage = null) { $parentPackages = (array) $parentPackage; $parentPackages[] = 'symfony/framework-bundle'; @@ -930,6 +931,10 @@ class Configuration implements ConfigurationInterface ->end() ->scalarNode('importmap_polyfill') ->info('The importmap name that will be used to load the polyfill. Set to false to disable.') + ->validate() + ->ifTrue() + ->thenInvalid('Invalid "importmap_polyfill" value. Must be either an importmap name or false.') + ->end() ->defaultValue('es-module-shims') ->end() ->arrayNode('importmap_script_attributes') @@ -1062,7 +1067,7 @@ class Configuration implements ConfigurationInterface ->validate()->castToArray()->end() ->end() ->scalarNode('translation_domain')->defaultValue('validators')->end() - ->enumNode('email_validation_mode')->values(['html5', 'loose', 'strict'])->end() + ->enumNode('email_validation_mode')->values(array_merge(class_exists(Email::class) ? Email::VALIDATION_MODES : ['html5-allow-no-tld', 'html5', 'strict'], ['loose']))->end() ->arrayNode('mapping') ->addDefaultsIfNotSet() ->fixXmlConfig('path') @@ -1192,8 +1197,7 @@ class Configuration implements ConfigurationInterface ->end() ->arrayNode('default_context') ->normalizeKeys(false) - ->useAttributeAsKey('name') - ->beforeNormalization() + ->validate() ->ifTrue(fn () => $this->debug && class_exists(JsonParser::class)) ->then(fn (array $v) => $v + [JsonDecode::DETAILED_ERROR_MESSAGES => true]) ->end() @@ -2089,6 +2093,9 @@ class Configuration implements ConfigurationInterface ->variableNode('md5')->end() ->end() ->end() + ->scalarNode('crypto_method') + ->info('The minimum version of TLS to accept; must be one of STREAM_CRYPTO_METHOD_TLSv*_CLIENT constants.') + ->end() ->arrayNode('extra') ->info('Extra options for specific HTTP client') ->normalizeKeys(false) @@ -2195,6 +2202,7 @@ class Configuration implements ConfigurationInterface ->end() ->arrayNode('envelope') ->info('Mailer Envelope configuration') + ->fixXmlConfig('recipient') ->children() ->scalarNode('sender')->end() ->arrayNode('recipients') diff --git a/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php b/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php index 32026a84d..40834b385 100644 --- a/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php +++ b/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php @@ -122,6 +122,8 @@ use Symfony\Component\Mime\Header\Headers; use Symfony\Component\Mime\MimeTypeGuesserInterface; use Symfony\Component\Mime\MimeTypes; use Symfony\Component\Notifier\Bridge as NotifierBridge; +use Symfony\Component\Notifier\Bridge\FakeChat\FakeChatTransportFactory; +use Symfony\Component\Notifier\Bridge\FakeSms\FakeSmsTransportFactory; use Symfony\Component\Notifier\ChatterInterface; use Symfony\Component\Notifier\Notifier; use Symfony\Component\Notifier\Recipient\Recipient; @@ -349,7 +351,7 @@ class FrameworkExtension extends Extension throw new LogicException('AssetMapper support cannot be enabled as the AssetMapper component is not installed. Try running "composer require symfony/asset-mapper".'); } - $this->registerAssetMapperConfiguration($config['asset_mapper'], $container, $loader, $this->readConfigEnabled('assets', $container, $config['assets'])); + $this->registerAssetMapperConfiguration($config['asset_mapper'], $container, $loader, $this->readConfigEnabled('assets', $container, $config['assets']), $this->readConfigEnabled('http_client', $container, $config['http_client'])); } else { $container->removeDefinition('cache.asset_mapper'); } @@ -733,7 +735,7 @@ class FrameworkExtension extends Extension $container->getDefinition('config_cache_factory')->setArguments([]); } - if (!$config['disallow_search_engine_index'] ?? false) { + if (!$config['disallow_search_engine_index']) { $container->removeDefinition('disallow_search_engine_index_response_listener'); } @@ -1330,7 +1332,7 @@ class FrameworkExtension extends Extension } } - private function registerAssetMapperConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $assetEnabled): void + private function registerAssetMapperConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader, bool $assetEnabled, bool $httpClientEnabled): void { $loader->load('asset_mapper.php'); @@ -1338,6 +1340,12 @@ class FrameworkExtension extends Extension $container->removeDefinition('asset_mapper.asset_package'); } + if (!$httpClientEnabled) { + $container->register('asset_mapper.http_client', HttpClientInterface::class) + ->addTag('container.error') + ->addError('You cannot use the AssetMapper integration since the HttpClient component is not enabled. Try enabling the "framework.http_client" config option.'); + } + $paths = $config['paths']; foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { if ($container->fileExists($dir = $bundle['path'].'/Resources/public') || $container->fileExists($dir = $bundle['path'].'/public')) { @@ -1507,7 +1515,7 @@ class FrameworkExtension extends Extension $defaultDir = $container->getParameterBag()->resolveValue($config['default_path']); foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { if ($container->fileExists($dir = $bundle['path'].'/Resources/translations') || $container->fileExists($dir = $bundle['path'].'/translations')) { - $dirs[] = $dir; + $dirs[] = $transPaths[] = $dir; } else { $nonExistingDirs[] = $dir; } @@ -1996,18 +2004,23 @@ class FrameworkExtension extends Extension $container->setParameter('serializer.default_context', $defaultContext); } - if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { + if ($container->hasDefinition('serializer.normalizer.object')) { $arguments = $container->getDefinition('serializer.normalizer.object')->getArguments(); - $context = ($arguments[6] ?? $defaultContext) + ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; - $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); + $context = $arguments[6] ?? $defaultContext; + + if (isset($config['circular_reference_handler']) && $config['circular_reference_handler']) { + $context += ['circular_reference_handler' => new Reference($config['circular_reference_handler'])]; + $container->getDefinition('serializer.normalizer.object')->setArgument(5, null); + } + + if ($config['max_depth_handler'] ?? false) { + $context += ['max_depth_handler' => new Reference($config['max_depth_handler'])]; + } + $container->getDefinition('serializer.normalizer.object')->setArgument(6, $context); } - if ($config['max_depth_handler'] ?? false) { - $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); - } + $container->getDefinition('serializer.normalizer.property')->setArgument(5, $defaultContext); } private function registerPropertyInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader): void @@ -2201,16 +2214,18 @@ class FrameworkExtension extends Extension $defaultMiddleware['after'][0]['arguments'] = [$bus['default_middleware']['allow_no_senders']]; $defaultMiddleware['after'][1]['arguments'] = [$bus['default_middleware']['allow_no_handlers']]; - // argument to add_bus_name_stamp_middleware - $defaultMiddleware['before'][0]['arguments'] = [$busId]; - $middleware = array_merge($defaultMiddleware['before'], $middleware, $defaultMiddleware['after']); } - foreach ($middleware as $middlewareItem) { + foreach ($middleware as $key => $middlewareItem) { if (!$validationEnabled && \in_array($middlewareItem['id'], ['validation', 'messenger.middleware.validation'], true)) { throw new LogicException('The Validation middleware is only available when the Validator component is installed and enabled. Try running "composer require symfony/validator".'); } + + // argument to add_bus_name_stamp_middleware + if ('add_bus_name_stamp_middleware' === $middlewareItem['id']) { + $middleware[$key]['arguments'] = [$busId]; + } } if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class)) { @@ -2267,14 +2282,17 @@ class FrameworkExtension extends Extension $transportRateLimiterReferences = []; foreach ($config['transports'] as $name => $transport) { $serializerId = $transport['serializer'] ?? 'messenger.default_serializer'; + $tags = [ + 'alias' => $name, + 'is_failure_transport' => \in_array($name, $failureTransports), + ]; + if (str_starts_with($transport['dsn'], 'sync://')) { + $tags['is_consumable'] = false; + } $transportDefinition = (new Definition(TransportInterface::class)) ->setFactory([new Reference('messenger.transport_factory'), 'createTransport']) ->setArguments([$transport['dsn'], $transport['options'] + ['transport_name' => $name], new Reference($serializerId)]) - ->addTag('messenger.receiver', [ - 'alias' => $name, - 'is_failure_transport' => \in_array($name, $failureTransports), - ] - ) + ->addTag('messenger.receiver', $tags) ; $container->setDefinition($transportId = 'messenger.transport.'.$name, $transportDefinition); $senderAliases[$name] = $transportId; @@ -2553,11 +2571,13 @@ class FrameworkExtension extends Extension ->setFactory([ScopingHttpClient::class, 'forBaseUri']) ->setArguments([new Reference('http_client.transport'), $baseUri, $scopeConfig]) ->addTag('http_client.client') + ->addTag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']) ; } else { $container->register($name, ScopingHttpClient::class) ->setArguments([new Reference('http_client.transport'), [$scope => $scopeConfig], $scope]) ->addTag('http_client.client') + ->addTag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']) ; } @@ -2644,7 +2664,6 @@ class FrameworkExtension extends Extension } $transports = $config['dsn'] ? ['main' => $config['dsn']] : $config['transports']; $container->getDefinition('mailer.transports')->setArgument(0, $transports); - $container->getDefinition('mailer.default_transport')->setArgument(0, current($transports)); $mailer = $container->getDefinition('mailer.mailer'); if (false === $messageBus = $config['message_bus']) { @@ -2753,7 +2772,7 @@ class FrameworkExtension extends Extension $container->removeDefinition('notifier.channel.email'); } - foreach (['texter', 'chatter', 'notifier.channel.chat', 'notifier.channel.email', 'notifier.channel.sms'] as $serviceId) { + foreach (['texter', 'chatter', 'notifier.channel.chat', 'notifier.channel.email', 'notifier.channel.sms', 'notifier.channel.push'] as $serviceId) { if (!$container->hasDefinition($serviceId)) { continue; } @@ -2800,8 +2819,6 @@ class FrameworkExtension extends Extension NotifierBridge\Engagespot\EngagespotTransportFactory::class => 'notifier.transport_factory.engagespot', NotifierBridge\Esendex\EsendexTransportFactory::class => 'notifier.transport_factory.esendex', NotifierBridge\Expo\ExpoTransportFactory::class => 'notifier.transport_factory.expo', - NotifierBridge\FakeChat\FakeChatTransportFactory::class => 'notifier.transport_factory.fake-chat', - NotifierBridge\FakeSms\FakeSmsTransportFactory::class => 'notifier.transport_factory.fake-sms', NotifierBridge\Firebase\FirebaseTransportFactory::class => 'notifier.transport_factory.firebase', NotifierBridge\FortySixElks\FortySixElksTransportFactory::class => 'notifier.transport_factory.forty-six-elks', NotifierBridge\FreeMobile\FreeMobileTransportFactory::class => 'notifier.transport_factory.free-mobile', @@ -2820,7 +2837,7 @@ class FrameworkExtension extends Extension NotifierBridge\Mastodon\MastodonTransportFactory::class => 'notifier.transport_factory.mastodon', NotifierBridge\Mattermost\MattermostTransportFactory::class => 'notifier.transport_factory.mattermost', NotifierBridge\Mercure\MercureTransportFactory::class => 'notifier.transport_factory.mercure', - NotifierBridge\MessageBird\MessageBirdTransport::class => 'notifier.transport_factory.message-bird', + NotifierBridge\MessageBird\MessageBirdTransportFactory::class => 'notifier.transport_factory.message-bird', NotifierBridge\MessageMedia\MessageMediaTransportFactory::class => 'notifier.transport_factory.message-media', NotifierBridge\MicrosoftTeams\MicrosoftTeamsTransportFactory::class => 'notifier.transport_factory.microsoft-teams', NotifierBridge\Mobyt\MobytTransportFactory::class => 'notifier.transport_factory.mobyt', @@ -2851,7 +2868,7 @@ class FrameworkExtension extends Extension NotifierBridge\Telegram\TelegramTransportFactory::class => 'notifier.transport_factory.telegram', NotifierBridge\Telnyx\TelnyxTransportFactory::class => 'notifier.transport_factory.telnyx', NotifierBridge\Termii\TermiiTransportFactory::class => 'notifier.transport_factory.termii', - NotifierBridge\TurboSms\TurboSmsTransport::class => 'notifier.transport_factory.turbo-sms', + NotifierBridge\TurboSms\TurboSmsTransportFactory::class => 'notifier.transport_factory.turbo-sms', NotifierBridge\Twilio\TwilioTransportFactory::class => 'notifier.transport_factory.twilio', NotifierBridge\Twitter\TwitterTransportFactory::class => 'notifier.transport_factory.twitter', NotifierBridge\Vonage\VonageTransportFactory::class => 'notifier.transport_factory.vonage', @@ -2872,27 +2889,33 @@ 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('$client', new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) - ->replaceArgument('$dispatcher', new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); + ->replaceArgument(0, new Reference(HubRegistry::class)) + ->replaceArgument(1, new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); } elseif (ContainerBuilder::willBeAvailable('symfony/mercure-notifier', NotifierBridge\Mercure\MercureTransportFactory::class, $parentPackages)) { $container->removeDefinition($classToServices[NotifierBridge\Mercure\MercureTransportFactory::class]); } - 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('$client', new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) - ->replaceArgument('$dispatcher', new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); + // don't use ContainerBuilder::willBeAvailable() as these are not needed in production + if (class_exists(FakeChatTransportFactory::class)) { + $container->getDefinition('notifier.transport_factory.fake-chat') + ->replaceArgument(0, new Reference('mailer', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->replaceArgument(1, new Reference('logger', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->addArgument(new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); + } else { + $container->removeDefinition('notifier.transport_factory.fake-chat'); } - 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('$client', new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) - ->replaceArgument('$dispatcher', new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); + // don't use ContainerBuilder::willBeAvailable() as these are not needed in production + if (class_exists(FakeSmsTransportFactory::class)) { + $container->getDefinition('notifier.transport_factory.fake-sms') + ->replaceArgument(0, new Reference('mailer', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->replaceArgument(1, new Reference('logger', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->addArgument(new Reference('event_dispatcher', ContainerBuilder::NULL_ON_INVALID_REFERENCE)) + ->addArgument(new Reference('http_client', ContainerBuilder::NULL_ON_INVALID_REFERENCE)); + } else { + $container->removeDefinition('notifier.transport_factory.fake-sms'); } if (isset($config['admin_recipients'])) { diff --git a/lib/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php b/lib/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php index c2a71d0a7..03274450d 100644 --- a/lib/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php +++ b/lib/symfony/framework-bundle/EventListener/ConsoleProfilerListener.php @@ -38,6 +38,8 @@ final class ConsoleProfilerListener implements EventSubscriberInterface /** @var \SplObjectStorage */ private \SplObjectStorage $parents; + private bool $disabled = false; + public function __construct( private readonly Profiler $profiler, private readonly RequestStack $requestStack, @@ -66,7 +68,7 @@ final class ConsoleProfilerListener implements EventSubscriberInterface $input = $event->getInput(); if (!$input->hasOption('profile') || !$input->getOption('profile')) { - $this->profiler->disable(); + $this->disabled = true; return; } @@ -92,7 +94,12 @@ final class ConsoleProfilerListener implements EventSubscriberInterface public function profile(ConsoleTerminateEvent $event): void { - if (!$this->cliMode || !$this->profiler->isEnabled()) { + $error = $this->error; + $this->error = null; + + if (!$this->cliMode || $this->disabled) { + $this->disabled = false; + return; } @@ -114,8 +121,7 @@ final class ConsoleProfilerListener implements EventSubscriberInterface $request->command->exitCode = $event->getExitCode(); $request->command->interruptedBySignal = $event->getInterruptingSignal(); - $profile = $this->profiler->collect($request, $request->getResponse(), $this->error); - $this->error = null; + $profile = $this->profiler->collect($request, $request->getResponse(), $error); $this->profiles[$request] = $profile; if ($this->parents[$request] = $this->requestStack->getParentRequest()) { diff --git a/lib/symfony/framework-bundle/FrameworkBundle.php b/lib/symfony/framework-bundle/FrameworkBundle.php index 4ba30a5c8..c371d10db 100644 --- a/lib/symfony/framework-bundle/FrameworkBundle.php +++ b/lib/symfony/framework-bundle/FrameworkBundle.php @@ -20,6 +20,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\RemoveUnusedSessionMarshallingHandlerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerRealRefPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TestServiceContainerWeakRefPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationUpdateCommandPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\VirtualRequestStackPass; use Symfony\Component\Cache\Adapter\ApcuAdapter; @@ -58,6 +59,7 @@ use Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass; use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass; use Symfony\Component\Routing\DependencyInjection\AddExpressionLanguageProvidersPass; use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass; +use Symfony\Component\Runtime\SymfonyRuntime; use Symfony\Component\Scheduler\DependencyInjection\AddScheduleMessengerPass; use Symfony\Component\Serializer\DependencyInjection\SerializerPass; use Symfony\Component\Translation\DependencyInjection\DataCollectorTranslatorPass; @@ -99,13 +101,19 @@ class FrameworkBundle extends Bundle { $_ENV['DOCTRINE_DEPRECATIONS'] = $_SERVER['DOCTRINE_DEPRECATIONS'] ??= 'trigger'; - $handler = ErrorHandler::register(null, false); + if (class_exists(SymfonyRuntime::class)) { + $handler = set_error_handler('var_dump'); + restore_error_handler(); + } else { + $handler = [ErrorHandler::register(null, false)]; + } - // When upgrading an existing Symfony application from 6.2 to 6.3, and - // the cache is warmed up, the service is not available yet, so we need - // to check if it exists. - if ($this->container->has('debug.error_handler_configurator')) { - $this->container->get('debug.error_handler_configurator')->configure($handler); + if (!$this->container->has('debug.error_handler_configurator')) { + // When upgrading an existing Symfony application from 6.2 to 6.3, and + // the cache is warmed up, the service is not available yet, so we need + // to check if it exists. + } elseif (\is_array($handler) && $handler[0] instanceof ErrorHandler) { + $this->container->get('debug.error_handler_configurator')->configure($handler[0]); } if ($this->container->getParameter('kernel.http_method_override')) { @@ -186,6 +194,7 @@ class FrameworkBundle extends Bundle // must be registered after MonologBundle's LoggerChannelPass $container->addCompilerPass(new ErrorLoggerCompilerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); $container->addCompilerPass(new VirtualRequestStackPass()); + $container->addCompilerPass(new TranslationUpdateCommandPass(), PassConfig::TYPE_BEFORE_REMOVING); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 2); diff --git a/lib/symfony/framework-bundle/HttpCache/HttpCache.php b/lib/symfony/framework-bundle/HttpCache/HttpCache.php index f312a7afe..481e8cf3c 100644 --- a/lib/symfony/framework-bundle/HttpCache/HttpCache.php +++ b/lib/symfony/framework-bundle/HttpCache/HttpCache.php @@ -37,7 +37,7 @@ class HttpCache extends BaseHttpCache /** * @param $cache The cache directory (default used if null) or the storage instance */ - public function __construct(KernelInterface $kernel, string|StoreInterface $cache = null, SurrogateInterface $surrogate = null, array $options = null) + public function __construct(KernelInterface $kernel, string|StoreInterface|null $cache = null, ?SurrogateInterface $surrogate = null, ?array $options = null) { $this->kernel = $kernel; $this->surrogate = $surrogate; @@ -60,7 +60,7 @@ class HttpCache extends BaseHttpCache parent::__construct($kernel, $this->createStore(), $this->createSurrogate(), array_merge($this->options, $this->getOptions())); } - protected function forward(Request $request, bool $catch = false, Response $entry = null): Response + protected function forward(Request $request, bool $catch = false, ?Response $entry = null): Response { $this->getKernel()->boot(); $this->getKernel()->getContainer()->set('cache', $this); diff --git a/lib/symfony/framework-bundle/Kernel/MicroKernelTrait.php b/lib/symfony/framework-bundle/Kernel/MicroKernelTrait.php index bbbfd5426..7d0de3d7c 100644 --- a/lib/symfony/framework-bundle/Kernel/MicroKernelTrait.php +++ b/lib/symfony/framework-bundle/Kernel/MicroKernelTrait.php @@ -217,7 +217,7 @@ trait MicroKernelTrait if (\is_array($controller) && [0, 1] === array_keys($controller) && $this === $controller[0]) { $route->setDefault('_controller', ['kernel', $controller[1]]); - } elseif ($controller instanceof \Closure && $this === ($r = new \ReflectionFunction($controller))->getClosureThis() && !str_contains($r->name, '{closure}')) { + } elseif ($controller instanceof \Closure && $this === ($r = new \ReflectionFunction($controller))->getClosureThis() && !str_contains($r->name, '{closure')) { $route->setDefault('_controller', ['kernel', $r->name]); } } diff --git a/lib/symfony/framework-bundle/KernelBrowser.php b/lib/symfony/framework-bundle/KernelBrowser.php index 45120e42b..8fb78790f 100644 --- a/lib/symfony/framework-bundle/KernelBrowser.php +++ b/lib/symfony/framework-bundle/KernelBrowser.php @@ -34,7 +34,7 @@ class KernelBrowser extends HttpKernelBrowser private bool $profiler = false; private bool $reboot = true; - public function __construct(KernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) + public function __construct(KernelInterface $kernel, array $server = [], ?History $history = null, ?CookieJar $cookieJar = null) { parent::__construct($kernel, $server, $history, $cookieJar); } diff --git a/lib/symfony/framework-bundle/README.md b/lib/symfony/framework-bundle/README.md index 14c600fac..220d72a8a 100644 --- a/lib/symfony/framework-bundle/README.md +++ b/lib/symfony/framework-bundle/README.md @@ -17,4 +17,4 @@ Resources [send Pull Requests](https://github.com/symfony/symfony/pulls) in the [main Symfony repository](https://github.com/symfony/symfony) -[3]: https://symfony.com/sponsor +[1]: https://symfony.com/sponsor diff --git a/lib/symfony/framework-bundle/Resources/config/asset_mapper.php b/lib/symfony/framework-bundle/Resources/config/asset_mapper.php index f41574d3b..404e7af18 100644 --- a/lib/symfony/framework-bundle/Resources/config/asset_mapper.php +++ b/lib/symfony/framework-bundle/Resources/config/asset_mapper.php @@ -54,6 +54,8 @@ return static function (ContainerConfigurator $container) { ]) ->alias(AssetMapperInterface::class, 'asset_mapper') + ->alias('asset_mapper.http_client', 'http_client') + ->set('asset_mapper.mapped_asset_factory', MappedAssetFactory::class) ->args([ service('asset_mapper.public_assets_path_resolver'), @@ -75,6 +77,7 @@ return static function (ContainerConfigurator $container) { param('kernel.project_dir'), abstract_arg('array of excluded path patterns'), abstract_arg('exclude dot files'), + param('kernel.debug'), ]) ->set('asset_mapper.public_assets_path_resolver', PublicAssetsPathResolver::class) @@ -196,7 +199,7 @@ return static function (ContainerConfigurator $container) { ]) ->set('asset_mapper.importmap.resolver', JsDelivrEsmResolver::class) - ->args([service('http_client')]) + ->args([service('asset_mapper.http_client')]) ->set('asset_mapper.importmap.renderer', ImportMapRenderer::class) ->args([ @@ -211,12 +214,12 @@ return static function (ContainerConfigurator $container) { ->set('asset_mapper.importmap.auditor', ImportMapAuditor::class) ->args([ service('asset_mapper.importmap.config_reader'), - service('http_client'), + service('asset_mapper.http_client'), ]) ->set('asset_mapper.importmap.update_checker', ImportMapUpdateChecker::class) ->args([ service('asset_mapper.importmap.config_reader'), - service('http_client'), + service('asset_mapper.http_client'), ]) ->set('asset_mapper.importmap.command.require', ImportMapRequireCommand::class) diff --git a/lib/symfony/framework-bundle/Resources/config/http_client.php b/lib/symfony/framework-bundle/Resources/config/http_client.php index a4c78d0ec..593b78fdd 100644 --- a/lib/symfony/framework-bundle/Resources/config/http_client.php +++ b/lib/symfony/framework-bundle/Resources/config/http_client.php @@ -39,6 +39,7 @@ return static function (ContainerConfigurator $container) { ->factory('current') ->args([[service('http_client.transport')]]) ->tag('http_client.client') + ->tag('kernel.reset', ['method' => 'reset', 'on_invalid' => 'ignore']) ->alias(HttpClientInterface::class, 'http_client') diff --git a/lib/symfony/framework-bundle/Resources/config/mailer.php b/lib/symfony/framework-bundle/Resources/config/mailer.php index 9eb545ca2..f1dc560ab 100644 --- a/lib/symfony/framework-bundle/Resources/config/mailer.php +++ b/lib/symfony/framework-bundle/Resources/config/mailer.php @@ -45,11 +45,7 @@ return static function (ContainerConfigurator $container) { tagged_iterator('mailer.transport_factory'), ]) - ->set('mailer.default_transport', TransportInterface::class) - ->factory([service('mailer.transport_factory'), 'fromString']) - ->args([ - abstract_arg('env(MAILER_DSN)'), - ]) + ->alias('mailer.default_transport', 'mailer.transports') ->alias(TransportInterface::class, 'mailer.default_transport') ->set('mailer.messenger.message_handler', MessageHandler::class) diff --git a/lib/symfony/framework-bundle/Resources/config/notifier.php b/lib/symfony/framework-bundle/Resources/config/notifier.php index 6ce674148..bcc124820 100644 --- a/lib/symfony/framework-bundle/Resources/config/notifier.php +++ b/lib/symfony/framework-bundle/Resources/config/notifier.php @@ -73,7 +73,10 @@ return static function (ContainerConfigurator $container) { ->tag('notifier.channel', ['channel' => 'email']) ->set('notifier.channel.push', PushChannel::class) - ->args([service('texter.transports'), service('messenger.default_bus')->ignoreOnInvalid()]) + ->args([ + service('texter.transports'), + abstract_arg('message bus'), + ]) ->tag('notifier.channel', ['channel' => 'push']) ->set('notifier.monolog_handler', NotifierHandler::class) diff --git a/lib/symfony/framework-bundle/Resources/config/profiling.php b/lib/symfony/framework-bundle/Resources/config/profiling.php index eaef79597..4ae34649b 100644 --- a/lib/symfony/framework-bundle/Resources/config/profiling.php +++ b/lib/symfony/framework-bundle/Resources/config/profiling.php @@ -40,7 +40,7 @@ return static function (ContainerConfigurator $container) { ->set('console_profiler_listener', ConsoleProfilerListener::class) ->args([ - service('profiler'), + service('.lazy_profiler'), service('.virtual_request_stack'), service('debug.stopwatch'), param('kernel.runtime_mode.cli'), @@ -48,6 +48,11 @@ return static function (ContainerConfigurator $container) { ]) ->tag('kernel.event_subscriber') + ->set('.lazy_profiler', Profiler::class) + ->factory('current') + ->args([[service('profiler')]]) + ->lazy() + ->set('.virtual_request_stack', VirtualRequestStack::class) ->args([service('request_stack')]) ->public() 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 ffa47c384..7d9828eeb 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 @@ -266,6 +266,7 @@ + @@ -299,6 +300,11 @@ + + + + + @@ -551,7 +557,7 @@ - + @@ -781,7 +787,7 @@ - + diff --git a/lib/symfony/framework-bundle/Resources/config/serializer.php b/lib/symfony/framework-bundle/Resources/config/serializer.php index 2311df0fc..c29258d52 100644 --- a/lib/symfony/framework-bundle/Resources/config/serializer.php +++ b/lib/symfony/framework-bundle/Resources/config/serializer.php @@ -60,7 +60,7 @@ return static function (ContainerConfigurator $container) { $container->services() ->set('serializer', Serializer::class) - ->args([[], []]) + ->args([[], [], []]) ->alias(SerializerInterface::class, 'serializer') ->alias(NormalizerInterface::class, 'serializer') @@ -116,7 +116,7 @@ return static function (ContainerConfigurator $container) { ->set('serializer.normalizer.translatable', TranslatableNormalizer::class) ->args(['$translator' => service('translator')]) - ->tag('serializer.normalizer', ['priority' => -890]) + ->tag('serializer.normalizer', ['priority' => -920]) ->set('serializer.normalizer.form_error', FormErrorNormalizer::class) ->tag('serializer.normalizer', ['priority' => -915]) @@ -129,6 +129,8 @@ return static function (ContainerConfigurator $container) { service('property_info')->ignoreOnInvalid(), service('serializer.mapping.class_discriminator_resolver')->ignoreOnInvalid(), null, + null, + service('property_info')->ignoreOnInvalid(), ]) ->tag('serializer.normalizer', ['priority' => -1000]) diff --git a/lib/symfony/framework-bundle/Resources/config/services.php b/lib/symfony/framework-bundle/Resources/config/services.php index 905e16f9b..5f280bdfb 100644 --- a/lib/symfony/framework-bundle/Resources/config/services.php +++ b/lib/symfony/framework-bundle/Resources/config/services.php @@ -100,6 +100,7 @@ return static function (ContainerConfigurator $container) { ->alias(HttpKernelInterface::class, 'http_kernel') ->set('request_stack', RequestStack::class) + ->tag('kernel.reset', ['method' => 'resetRequestFormats', 'on_invalid' => 'ignore']) ->public() ->alias(RequestStack::class, 'request_stack') diff --git a/lib/symfony/framework-bundle/Resources/config/session.php b/lib/symfony/framework-bundle/Resources/config/session.php index 907b1b584..2e481359a 100644 --- a/lib/symfony/framework-bundle/Resources/config/session.php +++ b/lib/symfony/framework-bundle/Resources/config/session.php @@ -90,6 +90,7 @@ return static function (ContainerConfigurator $container) { 'session_factory' => service('session.factory')->ignoreOnInvalid(), 'logger' => service('logger')->ignoreOnInvalid(), 'session_collector' => service('data_collector.request.session_collector')->ignoreOnInvalid(), + 'request_stack' => service('request_stack')->ignoreOnInvalid(), ]), param('kernel.debug'), param('session.storage.options'), diff --git a/lib/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php b/lib/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php index d1f1a5f34..13f8ff26a 100644 --- a/lib/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php +++ b/lib/symfony/framework-bundle/Routing/Attribute/AsRoutingConditionService.php @@ -42,7 +42,7 @@ use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; class AsRoutingConditionService extends AutoconfigureTag { public function __construct( - string $alias = null, + ?string $alias = null, int $priority = 0, ) { parent::__construct('routing.condition_service', ['alias' => $alias, 'priority' => $priority]); diff --git a/lib/symfony/framework-bundle/Routing/DelegatingLoader.php b/lib/symfony/framework-bundle/Routing/DelegatingLoader.php index df7e9348c..3239d1094 100644 --- a/lib/symfony/framework-bundle/Routing/DelegatingLoader.php +++ b/lib/symfony/framework-bundle/Routing/DelegatingLoader.php @@ -40,7 +40,7 @@ class DelegatingLoader extends BaseDelegatingLoader parent::__construct($resolver); } - public function load(mixed $resource, string $type = null): RouteCollection + public function load(mixed $resource, ?string $type = null): RouteCollection { if ($this->loading) { // This can happen if a fatal error occurs in parent::load(). diff --git a/lib/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php b/lib/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php index 538427aae..609502bca 100644 --- a/lib/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php +++ b/lib/symfony/framework-bundle/Routing/RedirectableCompiledUrlMatcher.php @@ -21,7 +21,7 @@ use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; */ class RedirectableCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface { - public function redirect(string $path, string $route, string $scheme = null): array + public function redirect(string $path, string $route, ?string $scheme = null): array { return [ '_controller' => 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction', diff --git a/lib/symfony/framework-bundle/Routing/Router.php b/lib/symfony/framework-bundle/Routing/Router.php index 3367ecec2..b264a8fa7 100644 --- a/lib/symfony/framework-bundle/Routing/Router.php +++ b/lib/symfony/framework-bundle/Routing/Router.php @@ -40,7 +40,7 @@ class Router extends BaseRouter implements WarmableInterface, ServiceSubscriberI /** * @param mixed $resource The main resource to load */ - public function __construct(ContainerInterface $container, mixed $resource, array $options = [], RequestContext $context = null, ContainerInterface $parameters = null, LoggerInterface $logger = null, string $defaultLocale = null) + public function __construct(ContainerInterface $container, mixed $resource, array $options = [], ?RequestContext $context = null, ?ContainerInterface $parameters = null, ?LoggerInterface $logger = null, ?string $defaultLocale = null) { $this->container = $container; $this->resource = $resource; diff --git a/lib/symfony/framework-bundle/Secrets/SodiumVault.php b/lib/symfony/framework-bundle/Secrets/SodiumVault.php index b6bb058b3..dcf79869f 100644 --- a/lib/symfony/framework-bundle/Secrets/SodiumVault.php +++ b/lib/symfony/framework-bundle/Secrets/SodiumVault.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Secrets; use Symfony\Component\DependencyInjection\EnvVarLoaderInterface; +use Symfony\Component\String\LazyString; use Symfony\Component\VarExporter\VarExporter; /** @@ -30,7 +31,7 @@ class SodiumVault extends AbstractVault implements EnvVarLoaderInterface * @param $decryptionKey A string or a stringable object that defines the private key to use to decrypt the vault * or null to store generated keys in the provided $secretsDir */ - public function __construct(string $secretsDir, #[\SensitiveParameter] string|\Stringable $decryptionKey = null) + public function __construct(string $secretsDir, #[\SensitiveParameter] string|\Stringable|null $decryptionKey = null) { $this->pathPrefix = rtrim(strtr($secretsDir, '/', \DIRECTORY_SEPARATOR), \DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR.basename($secretsDir).'.'; $this->decryptionKey = $decryptionKey; @@ -169,7 +170,14 @@ class SodiumVault extends AbstractVault implements EnvVarLoaderInterface public function loadEnvVars(): array { - return $this->list(true); + $envs = []; + $reveal = $this->reveal(...); + + foreach ($this->list() as $name => $value) { + $envs[$name] = LazyString::fromCallable($reveal, $name); + } + + return $envs; } private function loadKeys(): void diff --git a/lib/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php b/lib/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php index a6d4fed33..125aa45a7 100644 --- a/lib/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php +++ b/lib/symfony/framework-bundle/Test/BrowserKitAssertionsTrait.php @@ -43,7 +43,7 @@ trait BrowserKitAssertionsTrait self::assertThatForResponse(new ResponseConstraint\ResponseFormatSame(self::getRequest(), $expectedFormat), $message); } - public static function assertResponseRedirects(string $expectedLocation = null, int $expectedCode = null, string $message = ''): void + public static function assertResponseRedirects(?string $expectedLocation = null, ?int $expectedCode = null, string $message = ''): void { $constraint = new ResponseConstraint\ResponseIsRedirected(); if ($expectedLocation) { @@ -82,17 +82,17 @@ trait BrowserKitAssertionsTrait self::assertThatForResponse(new LogicalNot(new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue)), $message); } - public static function assertResponseHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void + public static function assertResponseHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void { self::assertThatForResponse(new ResponseConstraint\ResponseHasCookie($name, $path, $domain), $message); } - public static function assertResponseNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void + public static function assertResponseNotHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void { self::assertThatForResponse(new LogicalNot(new ResponseConstraint\ResponseHasCookie($name, $path, $domain)), $message); } - public static function assertResponseCookieValueSame(string $name, string $expectedValue, string $path = '/', string $domain = null, string $message = ''): void + public static function assertResponseCookieValueSame(string $name, string $expectedValue, string $path = '/', ?string $domain = null, string $message = ''): void { self::assertThatForResponse(LogicalAnd::fromConstraints( new ResponseConstraint\ResponseHasCookie($name, $path, $domain), @@ -105,17 +105,17 @@ trait BrowserKitAssertionsTrait self::assertThatForResponse(new ResponseConstraint\ResponseIsUnprocessable(), $message); } - public static function assertBrowserHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void + public static function assertBrowserHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void { self::assertThatForClient(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), $message); } - public static function assertBrowserNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void + public static function assertBrowserNotHasCookie(string $name, string $path = '/', ?string $domain = null, string $message = ''): void { self::assertThatForClient(new LogicalNot(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain)), $message); } - public static function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = false, string $path = '/', string $domain = null, string $message = ''): void + public static function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = false, string $path = '/', ?string $domain = null, string $message = ''): void { self::assertThatForClient(LogicalAnd::fromConstraints( new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), @@ -162,7 +162,7 @@ trait BrowserKitAssertionsTrait self::assertThat(self::getClient(), $constraint, $message); } - protected static function getClient(AbstractBrowser $newClient = null): ?AbstractBrowser + protected static function getClient(?AbstractBrowser $newClient = null): ?AbstractBrowser { static $client; diff --git a/lib/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php b/lib/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php index bed835fa1..01a27ea87 100644 --- a/lib/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php +++ b/lib/symfony/framework-bundle/Test/HttpClientAssertionsTrait.php @@ -14,13 +14,12 @@ namespace Symfony\Bundle\FrameworkBundle\Test; use Symfony\Bundle\FrameworkBundle\KernelBrowser; use Symfony\Component\HttpClient\DataCollector\HttpClientDataCollector; -/* +/** * @author Mathieu Santostefano */ - trait HttpClientAssertionsTrait { - public static function assertHttpClientRequest(string $expectedUrl, string $expectedMethod = 'GET', string|array $expectedBody = null, array $expectedHeaders = [], string $httpClientId = 'http_client'): void + public static function assertHttpClientRequest(string $expectedUrl, string $expectedMethod = 'GET', string|array|null $expectedBody = null, array $expectedHeaders = [], string $httpClientId = 'http_client'): void { /** @var KernelBrowser $client */ $client = static::getClient(); diff --git a/lib/symfony/framework-bundle/Test/KernelTestCase.php b/lib/symfony/framework-bundle/Test/KernelTestCase.php index 8d27b757f..1312f6592 100644 --- a/lib/symfony/framework-bundle/Test/KernelTestCase.php +++ b/lib/symfony/framework-bundle/Test/KernelTestCase.php @@ -45,6 +45,14 @@ abstract class KernelTestCase extends TestCase static::$booted = false; } + public static function tearDownAfterClass(): void + { + static::ensureKernelShutdown(); + static::$class = null; + static::$kernel = null; + static::$booted = false; + } + /** * @throws \RuntimeException * @throws \LogicException @@ -126,6 +134,12 @@ abstract class KernelTestCase extends TestCase if (null !== static::$kernel) { static::$kernel->boot(); $container = static::$kernel->getContainer(); + + if ($container->has('services_resetter')) { + // Instantiate the service because Container::reset() only resets services that have been used + $container->get('services_resetter'); + } + static::$kernel->shutdown(); static::$booted = false; diff --git a/lib/symfony/framework-bundle/Test/MailerAssertionsTrait.php b/lib/symfony/framework-bundle/Test/MailerAssertionsTrait.php index 83643421e..2308c3e2f 100644 --- a/lib/symfony/framework-bundle/Test/MailerAssertionsTrait.php +++ b/lib/symfony/framework-bundle/Test/MailerAssertionsTrait.php @@ -20,12 +20,12 @@ use Symfony\Component\Mime\Test\Constraint as MimeConstraint; trait MailerAssertionsTrait { - public static function assertEmailCount(int $count, string $transport = null, string $message = ''): void + public static function assertEmailCount(int $count, ?string $transport = null, string $message = ''): void { self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport), $message); } - public static function assertQueuedEmailCount(int $count, string $transport = null, string $message = ''): void + public static function assertQueuedEmailCount(int $count, ?string $transport = null, string $message = ''): void { self::assertThat(self::getMessageMailerEvents(), new MailerConstraint\EmailCount($count, $transport, true), $message); } @@ -103,12 +103,12 @@ trait MailerAssertionsTrait /** * @return MessageEvent[] */ - public static function getMailerEvents(string $transport = null): array + public static function getMailerEvents(?string $transport = null): array { return self::getMessageMailerEvents()->getEvents($transport); } - public static function getMailerEvent(int $index = 0, string $transport = null): ?MessageEvent + public static function getMailerEvent(int $index = 0, ?string $transport = null): ?MessageEvent { return self::getMailerEvents($transport)[$index] ?? null; } @@ -116,12 +116,12 @@ trait MailerAssertionsTrait /** * @return RawMessage[] */ - public static function getMailerMessages(string $transport = null): array + public static function getMailerMessages(?string $transport = null): array { return self::getMessageMailerEvents()->getMessages($transport); } - public static function getMailerMessage(int $index = 0, string $transport = null): ?RawMessage + public static function getMailerMessage(int $index = 0, ?string $transport = null): ?RawMessage { return self::getMailerMessages($transport)[$index] ?? null; } diff --git a/lib/symfony/framework-bundle/Test/NotificationAssertionsTrait.php b/lib/symfony/framework-bundle/Test/NotificationAssertionsTrait.php index 53d24cb12..2c4c5467d 100644 --- a/lib/symfony/framework-bundle/Test/NotificationAssertionsTrait.php +++ b/lib/symfony/framework-bundle/Test/NotificationAssertionsTrait.php @@ -17,17 +17,17 @@ use Symfony\Component\Notifier\Event\NotificationEvents; use Symfony\Component\Notifier\Message\MessageInterface; use Symfony\Component\Notifier\Test\Constraint as NotifierConstraint; -/* +/** * @author Smaïne Milianni */ trait NotificationAssertionsTrait { - public static function assertNotificationCount(int $count, string $transportName = null, string $message = ''): void + public static function assertNotificationCount(int $count, ?string $transportName = null, string $message = ''): void { self::assertThat(self::getNotificationEvents(), new NotifierConstraint\NotificationCount($count, $transportName), $message); } - public static function assertQueuedNotificationCount(int $count, string $transportName = null, string $message = ''): void + public static function assertQueuedNotificationCount(int $count, ?string $transportName = null, string $message = ''): void { self::assertThat(self::getNotificationEvents(), new NotifierConstraint\NotificationCount($count, $transportName, true), $message); } @@ -52,12 +52,12 @@ trait NotificationAssertionsTrait self::assertThat($notification, new LogicalNot(new NotifierConstraint\NotificationSubjectContains($text)), $message); } - public static function assertNotificationTransportIsEqual(MessageInterface $notification, string $transportName = null, string $message = ''): void + public static function assertNotificationTransportIsEqual(MessageInterface $notification, ?string $transportName = null, string $message = ''): void { self::assertThat($notification, new NotifierConstraint\NotificationTransportIsEqual($transportName), $message); } - public static function assertNotificationTransportIsNotEqual(MessageInterface $notification, string $transportName = null, string $message = ''): void + public static function assertNotificationTransportIsNotEqual(MessageInterface $notification, ?string $transportName = null, string $message = ''): void { self::assertThat($notification, new LogicalNot(new NotifierConstraint\NotificationTransportIsEqual($transportName)), $message); } @@ -65,12 +65,12 @@ trait NotificationAssertionsTrait /** * @return MessageEvent[] */ - public static function getNotifierEvents(string $transportName = null): array + public static function getNotifierEvents(?string $transportName = null): array { return self::getNotificationEvents()->getEvents($transportName); } - public static function getNotifierEvent(int $index = 0, string $transportName = null): ?MessageEvent + public static function getNotifierEvent(int $index = 0, ?string $transportName = null): ?MessageEvent { return self::getNotifierEvents($transportName)[$index] ?? null; } @@ -78,12 +78,12 @@ trait NotificationAssertionsTrait /** * @return MessageInterface[] */ - public static function getNotifierMessages(string $transportName = null): array + public static function getNotifierMessages(?string $transportName = null): array { return self::getNotificationEvents()->getMessages($transportName); } - public static function getNotifierMessage(int $index = 0, string $transportName = null): ?MessageInterface + public static function getNotifierMessage(int $index = 0, ?string $transportName = null): ?MessageInterface { return self::getNotifierMessages($transportName)[$index] ?? null; } diff --git a/lib/symfony/framework-bundle/Test/TestBrowserToken.php b/lib/symfony/framework-bundle/Test/TestBrowserToken.php index 8bf365eb0..25d71d084 100644 --- a/lib/symfony/framework-bundle/Test/TestBrowserToken.php +++ b/lib/symfony/framework-bundle/Test/TestBrowserToken.php @@ -23,7 +23,7 @@ class TestBrowserToken extends AbstractToken { private string $firewallName; - public function __construct(array $roles = [], UserInterface $user = null, string $firewallName = 'main') + public function __construct(array $roles = [], ?UserInterface $user = null, string $firewallName = 'main') { parent::__construct($roles); diff --git a/lib/symfony/framework-bundle/Translation/Translator.php b/lib/symfony/framework-bundle/Translation/Translator.php index 04b56308f..9b0778a57 100644 --- a/lib/symfony/framework-bundle/Translation/Translator.php +++ b/lib/symfony/framework-bundle/Translation/Translator.php @@ -118,7 +118,7 @@ class Translator extends BaseTranslator implements WarmableInterface return []; } - public function addResource(string $format, mixed $resource, string $locale, string $domain = null): void + public function addResource(string $format, mixed $resource, string $locale, ?string $domain = null): void { if ($this->resourceFiles) { $this->addResourceFiles(); diff --git a/lib/symfony/framework-bundle/composer.json b/lib/symfony/framework-bundle/composer.json index 3aedebd74..c3aab8455 100644 --- a/lib/symfony/framework-bundle/composer.json +++ b/lib/symfony/framework-bundle/composer.json @@ -21,7 +21,7 @@ "ext-xml": "*", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/config": "^6.1|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4.12|^7.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.1|^7.0", "symfony/event-dispatcher": "^5.4|^6.0|^7.0", @@ -57,7 +57,7 @@ "symfony/notifier": "^5.4|^6.0|^7.0", "symfony/process": "^5.4|^6.0|^7.0", "symfony/rate-limiter": "^5.4|^6.0|^7.0", - "symfony/scheduler": "^6.4|^7.0", + "symfony/scheduler": "^6.4.4|^7.0.4", "symfony/security-bundle": "^5.4|^6.0|^7.0", "symfony/semaphore": "^5.4|^6.0|^7.0", "symfony/serializer": "^6.4|^7.0", @@ -72,7 +72,7 @@ "symfony/uid": "^5.4|^6.0|^7.0", "symfony/web-link": "^5.4|^6.0|^7.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "twig/twig": "^2.10|^3.0" + "twig/twig": "^2.10|^3.0.4" }, "conflict": { "doctrine/annotations": "<1.13.1", @@ -93,7 +93,8 @@ "symfony/mime": "<6.4", "symfony/property-info": "<5.4", "symfony/property-access": "<5.4", - "symfony/scheduler": "<6.4", + "symfony/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6", + "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/serializer": "<6.4", "symfony/security-csrf": "<5.4", "symfony/security-core": "<5.4", diff --git a/lib/symfony/http-foundation/BinaryFileResponse.php b/lib/symfony/http-foundation/BinaryFileResponse.php index ca18c92f1..c22f283cb 100644 --- a/lib/symfony/http-foundation/BinaryFileResponse.php +++ b/lib/symfony/http-foundation/BinaryFileResponse.php @@ -45,7 +45,7 @@ class BinaryFileResponse extends Response * @param bool $autoEtag Whether the ETag header should be automatically set * @param bool $autoLastModified Whether the Last-Modified header should be automatically set */ - public function __construct(\SplFileInfo|string $file, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) + public function __construct(\SplFileInfo|string $file, int $status = 200, array $headers = [], bool $public = true, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) { parent::__construct(null, $status, $headers); @@ -63,7 +63,7 @@ class BinaryFileResponse extends Response * * @throws FileException */ - public function setFile(\SplFileInfo|string $file, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true): static + public function setFile(\SplFileInfo|string $file, ?string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true): static { if (!$file instanceof File) { if ($file instanceof \SplFileInfo) { @@ -217,15 +217,19 @@ class BinaryFileResponse extends Response } if ('x-accel-redirect' === strtolower($type)) { // Do X-Accel-Mapping substitutions. - // @link https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/#x-accel-redirect - $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); + // @link https://github.com/rack/rack/blob/main/lib/rack/sendfile.rb + // @link https://mattbrictson.com/blog/accelerated-rails-downloads + if (!$request->headers->has('X-Accel-Mapping')) { + throw new \LogicException('The "X-Accel-Mapping" header must be set when "X-Sendfile-Type" is set to "X-Accel-Redirect".'); + } + $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping'), ',='); foreach ($parts as $part) { [$pathPrefix, $location] = $part; if (str_starts_with($path, $pathPrefix)) { $path = $location.substr($path, \strlen($pathPrefix)); // Only set X-Accel-Redirect header if a valid URI can be produced // as nginx does not serve arbitrary file paths. - $this->headers->set($type, $path); + $this->headers->set($type, rawurlencode($path)); $this->maxlen = 0; break; } diff --git a/lib/symfony/http-foundation/Cookie.php b/lib/symfony/http-foundation/Cookie.php index 706f5ca25..4a3b73608 100644 --- a/lib/symfony/http-foundation/Cookie.php +++ b/lib/symfony/http-foundation/Cookie.php @@ -77,7 +77,7 @@ class Cookie * @param self::SAMESITE_*|''|null $sameSite * @param bool $partitioned */ - public static function create(string $name, string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX /* , bool $partitioned = false */): self + public static function create(string $name, ?string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX /* , bool $partitioned = false */): self { $partitioned = 9 < \func_num_args() ? func_get_arg(9) : false; @@ -97,7 +97,7 @@ class Cookie * * @throws \InvalidArgumentException */ - public function __construct(string $name, string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX, bool $partitioned = false) + public function __construct(string $name, ?string $value = null, int|string|\DateTimeInterface $expire = 0, ?string $path = '/', ?string $domain = null, ?bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX, bool $partitioned = false) { // from PHP source code if ($raw && false !== strpbrk($name, self::RESERVED_CHARS_LIST)) { diff --git a/lib/symfony/http-foundation/Exception/SessionNotFoundException.php b/lib/symfony/http-foundation/Exception/SessionNotFoundException.php index 94b0cb69a..80a21bf15 100644 --- a/lib/symfony/http-foundation/Exception/SessionNotFoundException.php +++ b/lib/symfony/http-foundation/Exception/SessionNotFoundException.php @@ -20,7 +20,7 @@ namespace Symfony\Component\HttpFoundation\Exception; */ class SessionNotFoundException extends \LogicException implements RequestExceptionInterface { - public function __construct(string $message = 'There is currently no session available.', int $code = 0, \Throwable $previous = null) + public function __construct(string $message = 'There is currently no session available.', int $code = 0, ?\Throwable $previous = null) { parent::__construct($message, $code, $previous); } diff --git a/lib/symfony/http-foundation/File/File.php b/lib/symfony/http-foundation/File/File.php index e8ce4bcf8..34ca5a537 100644 --- a/lib/symfony/http-foundation/File/File.php +++ b/lib/symfony/http-foundation/File/File.php @@ -82,7 +82,7 @@ class File extends \SplFileInfo * * @throws FileException if the target file could not be created */ - public function move(string $directory, string $name = null): self + public function move(string $directory, ?string $name = null): self { $target = $this->getTargetFile($directory, $name); @@ -112,7 +112,7 @@ class File extends \SplFileInfo return $content; } - protected function getTargetFile(string $directory, string $name = null): self + protected function getTargetFile(string $directory, ?string $name = null): self { if (!is_dir($directory)) { if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) { diff --git a/lib/symfony/http-foundation/File/UploadedFile.php b/lib/symfony/http-foundation/File/UploadedFile.php index e27cf3812..f475d028d 100644 --- a/lib/symfony/http-foundation/File/UploadedFile.php +++ b/lib/symfony/http-foundation/File/UploadedFile.php @@ -60,7 +60,7 @@ class UploadedFile extends File * @throws FileException If file_uploads is disabled * @throws FileNotFoundException If the file does not exist */ - public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, bool $test = false) + public function __construct(string $path, string $originalName, ?string $mimeType = null, ?int $error = null, bool $test = false) { $this->originalName = $this->getName($originalName); $this->mimeType = $mimeType ?: 'application/octet-stream'; @@ -158,7 +158,7 @@ class UploadedFile extends File * * @throws FileException if, for any reason, the file could not have been moved */ - public function move(string $directory, string $name = null): File + public function move(string $directory, ?string $name = null): File { if ($this->isValid()) { if ($this->test) { diff --git a/lib/symfony/http-foundation/HeaderBag.php b/lib/symfony/http-foundation/HeaderBag.php index 9a3d5549f..4dd777f16 100644 --- a/lib/symfony/http-foundation/HeaderBag.php +++ b/lib/symfony/http-foundation/HeaderBag.php @@ -65,7 +65,7 @@ class HeaderBag implements \IteratorAggregate, \Countable, \Stringable * * @return ($key is null ? array> : list) */ - public function all(string $key = null): array + public function all(?string $key = null): array { if (null !== $key) { return $this->headers[strtr($key, self::UPPER, self::LOWER)] ?? []; @@ -110,7 +110,7 @@ class HeaderBag implements \IteratorAggregate, \Countable, \Stringable /** * Returns the first header by name or the default one. */ - public function get(string $key, string $default = null): ?string + public function get(string $key, ?string $default = null): ?string { $headers = $this->all($key); @@ -197,7 +197,7 @@ class HeaderBag implements \IteratorAggregate, \Countable, \Stringable * * @throws \RuntimeException When the HTTP header is not parseable */ - public function getDate(string $key, \DateTimeInterface $default = null): ?\DateTimeInterface + public function getDate(string $key, ?\DateTimeInterface $default = null): ?\DateTimeInterface { if (null === $value = $this->get($key)) { return null !== $default ? \DateTimeImmutable::createFromInterface($default) : null; diff --git a/lib/symfony/http-foundation/HeaderUtils.php b/lib/symfony/http-foundation/HeaderUtils.php index 3456edace..110896e17 100644 --- a/lib/symfony/http-foundation/HeaderUtils.php +++ b/lib/symfony/http-foundation/HeaderUtils.php @@ -286,7 +286,11 @@ class HeaderUtils } foreach ($partMatches as $matches) { - $parts[] = '' === $separators ? self::unquote($matches[0][0]) : self::groupParts($matches, $separators, false); + if ('' === $separators && '' !== $unquoted = self::unquote($matches[0][0])) { + $parts[] = $unquoted; + } elseif ($groupedParts = self::groupParts($matches, $separators, false)) { + $parts[] = $groupedParts; + } } return $parts; diff --git a/lib/symfony/http-foundation/InputBag.php b/lib/symfony/http-foundation/InputBag.php index 7676d9fe7..5acf35fec 100644 --- a/lib/symfony/http-foundation/InputBag.php +++ b/lib/symfony/http-foundation/InputBag.php @@ -84,7 +84,7 @@ final class InputBag extends ParameterBag * * @return ?T */ - public function getEnum(string $key, string $class, \BackedEnum $default = null): ?\BackedEnum + public function getEnum(string $key, string $class, ?\BackedEnum $default = null): ?\BackedEnum { try { return parent::getEnum($key, $class, $default); diff --git a/lib/symfony/http-foundation/IpUtils.php b/lib/symfony/http-foundation/IpUtils.php index ceab620c2..18b1c5faf 100644 --- a/lib/symfony/http-foundation/IpUtils.php +++ b/lib/symfony/http-foundation/IpUtils.php @@ -182,6 +182,16 @@ class IpUtils */ public static function anonymize(string $ip): string { + /** + * If the IP contains a % symbol, then it is a local-link address with scoping according to RFC 4007 + * In that case, we only care about the part before the % symbol, as the following functions, can only work with + * the IP address itself. As the scope can leak information (containing interface name), we do not want to + * include it in our anonymized IP data. + */ + if (str_contains($ip, '%')) { + $ip = substr($ip, 0, strpos($ip, '%')); + } + $wrappedIPv6 = false; if (str_starts_with($ip, '[') && str_ends_with($ip, ']')) { $wrappedIPv6 = true; diff --git a/lib/symfony/http-foundation/JsonResponse.php b/lib/symfony/http-foundation/JsonResponse.php index 8dd250a36..93c5751f2 100644 --- a/lib/symfony/http-foundation/JsonResponse.php +++ b/lib/symfony/http-foundation/JsonResponse.php @@ -75,7 +75,7 @@ class JsonResponse extends Response * * @throws \InvalidArgumentException When the callback name is not valid */ - public function setCallback(string $callback = null): static + public function setCallback(?string $callback = null): static { if (1 > \func_num_args()) { trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); diff --git a/lib/symfony/http-foundation/ParameterBag.php b/lib/symfony/http-foundation/ParameterBag.php index 0456e474c..48fa4b233 100644 --- a/lib/symfony/http-foundation/ParameterBag.php +++ b/lib/symfony/http-foundation/ParameterBag.php @@ -38,7 +38,7 @@ class ParameterBag implements \IteratorAggregate, \Countable * * @param string|null $key The name of the parameter to return or null to get them all */ - public function all(string $key = null): array + public function all(?string $key = null): array { if (null === $key) { return $this->parameters; @@ -174,7 +174,7 @@ class ParameterBag implements \IteratorAggregate, \Countable * * @return ?T */ - public function getEnum(string $key, string $class, \BackedEnum $default = null): ?\BackedEnum + public function getEnum(string $key, string $class, ?\BackedEnum $default = null): ?\BackedEnum { $value = $this->get($key); diff --git a/lib/symfony/http-foundation/RedirectResponse.php b/lib/symfony/http-foundation/RedirectResponse.php index a001df81d..408629e36 100644 --- a/lib/symfony/http-foundation/RedirectResponse.php +++ b/lib/symfony/http-foundation/RedirectResponse.php @@ -85,6 +85,7 @@ class RedirectResponse extends Response ', htmlspecialchars($url, \ENT_QUOTES, 'UTF-8'))); $this->headers->set('Location', $url); + $this->headers->set('Content-Type', 'text/html; charset=utf-8'); return $this; } diff --git a/lib/symfony/http-foundation/Request.php b/lib/symfony/http-foundation/Request.php index 10f3a758f..42a3a8a2c 100644 --- a/lib/symfony/http-foundation/Request.php +++ b/lib/symfony/http-foundation/Request.php @@ -11,6 +11,7 @@ namespace Symfony\Component\HttpFoundation; +use Symfony\Component\HttpFoundation\Exception\BadRequestException; use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; use Symfony\Component\HttpFoundation\Exception\JsonException; use Symfony\Component\HttpFoundation\Exception\SessionNotFoundException; @@ -326,6 +327,8 @@ class Request * @param array $files The request files ($_FILES) * @param array $server The server parameters ($_SERVER) * @param string|resource|null $content The raw body data + * + * @throws BadRequestException When the URI is invalid */ public static function create(string $uri, string $method = 'GET', array $parameters = [], array $cookies = [], array $files = [], array $server = [], $content = null): static { @@ -348,11 +351,20 @@ class Request $server['PATH_INFO'] = ''; $server['REQUEST_METHOD'] = strtoupper($method); - $components = parse_url($uri); - if (false === $components) { - trigger_deprecation('symfony/http-foundation', '6.3', 'Calling "%s()" with an invalid URI is deprecated.', __METHOD__); - $components = []; + if (false === $components = parse_url(\strlen($uri) !== strcspn($uri, '?#') ? $uri : $uri.'#')) { + throw new BadRequestException('Invalid URI.'); } + + if (false !== ($i = strpos($uri, '\\')) && $i < strcspn($uri, '?#')) { + throw new BadRequestException('Invalid URI: A URI cannot contain a backslash.'); + } + if (\strlen($uri) !== strcspn($uri, "\r\n\t")) { + throw new BadRequestException('Invalid URI: A URI cannot contain CR/LF/TAB characters.'); + } + if ('' !== $uri && (\ord($uri[0]) <= 32 || \ord($uri[-1]) <= 32)) { + throw new BadRequestException('Invalid URI: A URI must not start nor end with ASCII control characters or spaces.'); + } + if (isset($components['host'])) { $server['SERVER_NAME'] = $components['host']; $server['HTTP_HOST'] = $components['host']; @@ -448,7 +460,7 @@ class Request * @param array|null $files The FILES parameters * @param array|null $server The SERVER parameters */ - public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null): static + public function duplicate(?array $query = null, ?array $request = null, ?array $attributes = null, ?array $cookies = null, ?array $files = null, ?array $server = null): static { $dup = clone $this; if (null !== $query) { @@ -1230,7 +1242,7 @@ class Request } if (!preg_match('/^[A-Z]++$/D', $method)) { - throw new SuspiciousOperationException(sprintf('Invalid method override "%s".', $method)); + throw new SuspiciousOperationException('Invalid HTTP method override.'); } return $this->method = $method; @@ -1454,7 +1466,7 @@ class Request public function getProtocolVersion(): ?string { if ($this->isFromTrustedProxy()) { - preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via') ?? '', $matches); + preg_match('~^(HTTP/)?([1-9]\.[0-9])\b~', $this->headers->get('Via') ?? '', $matches); if ($matches) { return 'HTTP/'.$matches[2]; @@ -1606,7 +1618,7 @@ class Request * * @param string[] $locales An array of ordered available locales */ - public function getPreferredLanguage(array $locales = null): ?string + public function getPreferredLanguage(?array $locales = null): ?string { $preferredLanguages = $this->getLanguages(); @@ -2004,7 +2016,7 @@ class Request * getPort(), isSecure(), getHost(), getClientIps(), getBaseUrl() etc. Thus, we try to cache the results for * best performance. */ - private function getTrustedValues(int $type, string $ip = null): array + private function getTrustedValues(int $type, ?string $ip = null): array { $cacheKey = $type."\0".((self::$trustedHeaderSet & $type) ? $this->headers->get(self::TRUSTED_HEADERS[$type]) : ''); $cacheKey .= "\0".$ip."\0".$this->headers->get(self::TRUSTED_HEADERS[self::HEADER_FORWARDED]); diff --git a/lib/symfony/http-foundation/RequestMatcher.php b/lib/symfony/http-foundation/RequestMatcher.php index ac155fa30..b3ca3715d 100644 --- a/lib/symfony/http-foundation/RequestMatcher.php +++ b/lib/symfony/http-foundation/RequestMatcher.php @@ -51,7 +51,7 @@ class RequestMatcher implements RequestMatcherInterface * @param string|string[]|null $ips * @param string|string[]|null $schemes */ - public function __construct(string $path = null, string $host = null, string|array $methods = null, string|array $ips = null, array $attributes = [], string|array $schemes = null, int $port = null) + public function __construct(?string $path = null, ?string $host = null, string|array|null $methods = null, string|array|null $ips = null, array $attributes = [], string|array|null $schemes = null, ?int $port = null) { $this->matchPath($path); $this->matchHost($host); diff --git a/lib/symfony/http-foundation/RequestStack.php b/lib/symfony/http-foundation/RequestStack.php index 5aa8ba793..ca61eef29 100644 --- a/lib/symfony/http-foundation/RequestStack.php +++ b/lib/symfony/http-foundation/RequestStack.php @@ -106,4 +106,11 @@ class RequestStack throw new SessionNotFoundException(); } + + public function resetRequestFormats(): void + { + static $resetRequestFormats; + $resetRequestFormats ??= \Closure::bind(static fn () => self::$formats = null, null, Request::class); + $resetRequestFormats(); + } } diff --git a/lib/symfony/http-foundation/Response.php b/lib/symfony/http-foundation/Response.php index ef6ece002..a43e7a9ac 100644 --- a/lib/symfony/http-foundation/Response.php +++ b/lib/symfony/http-foundation/Response.php @@ -355,23 +355,21 @@ class Response $replace = false; // As recommended by RFC 8297, PHP automatically copies headers from previous 103 responses, we need to deal with that if headers changed - if (103 === $statusCode) { - $previousValues = $this->sentHeaders[$name] ?? null; - if ($previousValues === $values) { - // Header already sent in a previous response, it will be automatically copied in this response by PHP - continue; - } - - $replace = 0 === strcasecmp($name, 'Content-Type'); - - if (null !== $previousValues && array_diff($previousValues, $values)) { - header_remove($name); - $previousValues = null; - } - - $newValues = null === $previousValues ? $values : array_diff($values, $previousValues); + $previousValues = $this->sentHeaders[$name] ?? null; + if ($previousValues === $values) { + // Header already sent in a previous response, it will be automatically copied in this response by PHP + continue; } + $replace = 0 === strcasecmp($name, 'Content-Type'); + + if (null !== $previousValues && array_diff($previousValues, $values)) { + header_remove($name); + $previousValues = null; + } + + $newValues = null === $previousValues ? $values : array_diff($values, $previousValues); + foreach ($newValues as $value) { header($name.': '.$value, $replace, $this->statusCode); } @@ -497,7 +495,7 @@ class Response * * @final */ - public function setStatusCode(int $code, string $text = null): static + public function setStatusCode(int $code, ?string $text = null): static { $this->statusCode = $code; if ($this->isInvalid()) { @@ -762,7 +760,7 @@ class Response * * @final */ - public function setExpires(\DateTimeInterface $date = null): static + public function setExpires(?\DateTimeInterface $date = null): static { if (1 > \func_num_args()) { trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -943,7 +941,7 @@ class Response * * @final */ - public function setLastModified(\DateTimeInterface $date = null): static + public function setLastModified(?\DateTimeInterface $date = null): static { if (1 > \func_num_args()) { trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -981,7 +979,7 @@ class Response * * @final */ - public function setEtag(string $etag = null, bool $weak = false): static + public function setEtag(?string $etag = null, bool $weak = false): static { if (1 > \func_num_args()) { trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -1284,7 +1282,7 @@ class Response * * @final */ - public function isRedirect(string $location = null): bool + public function isRedirect(?string $location = null): bool { return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location')); } diff --git a/lib/symfony/http-foundation/ResponseHeaderBag.php b/lib/symfony/http-foundation/ResponseHeaderBag.php index 10450ca5e..376357d01 100644 --- a/lib/symfony/http-foundation/ResponseHeaderBag.php +++ b/lib/symfony/http-foundation/ResponseHeaderBag.php @@ -86,7 +86,7 @@ class ResponseHeaderBag extends HeaderBag } } - public function all(string $key = null): array + public function all(?string $key = null): array { $headers = parent::all(); @@ -183,7 +183,7 @@ class ResponseHeaderBag extends HeaderBag * * @return void */ - public function removeCookie(string $name, ?string $path = '/', string $domain = null) + public function removeCookie(string $name, ?string $path = '/', ?string $domain = null) { $path ??= '/'; @@ -234,11 +234,15 @@ class ResponseHeaderBag extends HeaderBag /** * Clears a cookie in the browser. * + * @param bool $partitioned + * * @return void */ - public function clearCookie(string $name, ?string $path = '/', string $domain = null, bool $secure = false, bool $httpOnly = true, string $sameSite = null) + public function clearCookie(string $name, ?string $path = '/', ?string $domain = null, bool $secure = false, bool $httpOnly = true, ?string $sameSite = null /* , bool $partitioned = false */) { - $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite)); + $partitioned = 6 < \func_num_args() ? \func_get_arg(6) : false; + + $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, $sameSite, $partitioned)); } /** diff --git a/lib/symfony/http-foundation/ServerBag.php b/lib/symfony/http-foundation/ServerBag.php index 3e912cb80..09fc38664 100644 --- a/lib/symfony/http-foundation/ServerBag.php +++ b/lib/symfony/http-foundation/ServerBag.php @@ -29,7 +29,7 @@ class ServerBag extends ParameterBag foreach ($this->parameters as $key => $value) { if (str_starts_with($key, 'HTTP_')) { $headers[substr($key, 5)] = $value; - } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true)) { + } elseif (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH', 'CONTENT_MD5'], true) && '' !== $value) { $headers[$key] = $value; } } diff --git a/lib/symfony/http-foundation/Session/Session.php b/lib/symfony/http-foundation/Session/Session.php index b45be2f8c..5b6db1754 100644 --- a/lib/symfony/http-foundation/Session/Session.php +++ b/lib/symfony/http-foundation/Session/Session.php @@ -40,7 +40,7 @@ class Session implements FlashBagAwareSessionInterface, \IteratorAggregate, \Cou private int $usageIndex = 0; private ?\Closure $usageReporter; - public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null, callable $usageReporter = null) + public function __construct(?SessionStorageInterface $storage = null, ?AttributeBagInterface $attributes = null, ?FlashBagInterface $flashes = null, ?callable $usageReporter = null) { $this->storage = $storage ?? new NativeSessionStorage(); $this->usageReporter = null === $usageReporter ? null : $usageReporter(...); @@ -151,14 +151,14 @@ class Session implements FlashBagAwareSessionInterface, \IteratorAggregate, \Cou return true; } - public function invalidate(int $lifetime = null): bool + public function invalidate(?int $lifetime = null): bool { $this->storage->clear(); return $this->migrate(true, $lifetime); } - public function migrate(bool $destroy = false, int $lifetime = null): bool + public function migrate(bool $destroy = false, ?int $lifetime = null): bool { return $this->storage->regenerate($destroy, $lifetime); } diff --git a/lib/symfony/http-foundation/Session/SessionFactory.php b/lib/symfony/http-foundation/Session/SessionFactory.php index cdb6af51e..c06ed4b7d 100644 --- a/lib/symfony/http-foundation/Session/SessionFactory.php +++ b/lib/symfony/http-foundation/Session/SessionFactory.php @@ -26,7 +26,7 @@ class SessionFactory implements SessionFactoryInterface private SessionStorageFactoryInterface $storageFactory; private ?\Closure $usageReporter; - public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, callable $usageReporter = null) + public function __construct(RequestStack $requestStack, SessionStorageFactoryInterface $storageFactory, ?callable $usageReporter = null) { $this->requestStack = $requestStack; $this->storageFactory = $storageFactory; diff --git a/lib/symfony/http-foundation/Session/SessionInterface.php b/lib/symfony/http-foundation/Session/SessionInterface.php index 534883d2d..07785a6f4 100644 --- a/lib/symfony/http-foundation/Session/SessionInterface.php +++ b/lib/symfony/http-foundation/Session/SessionInterface.php @@ -62,7 +62,7 @@ interface SessionInterface * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. */ - public function invalidate(int $lifetime = null): bool; + public function invalidate(?int $lifetime = null): bool; /** * Migrates the current session to a new session id while maintaining all @@ -74,7 +74,7 @@ interface SessionInterface * to expire with browser session. Time is in seconds, and is * not a Unix timestamp. */ - public function migrate(bool $destroy = false, int $lifetime = null): bool; + public function migrate(bool $destroy = false, ?int $lifetime = null): bool; /** * Force the session to be saved and closed. diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php index f6e73f9e6..f8c6151a4 100644 --- a/lib/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/lib/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -28,7 +28,7 @@ class NativeFileSessionHandler extends \SessionHandler * @throws \InvalidArgumentException On invalid $savePath * @throws \RuntimeException When failing to create the save directory */ - public function __construct(string $savePath = null) + public function __construct(?string $savePath = null) { $baseDir = $savePath ??= \ini_get('session.save_path'); diff --git a/lib/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/lib/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php index 1e8f9c6c4..9cee76ddf 100644 --- a/lib/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/lib/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php @@ -151,7 +151,7 @@ class PdoSessionHandler extends AbstractSessionHandler * * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION */ - public function __construct(#[\SensitiveParameter] \PDO|string $pdoOrDsn = null, #[\SensitiveParameter] array $options = []) + public function __construct(#[\SensitiveParameter] \PDO|string|null $pdoOrDsn = null, #[\SensitiveParameter] array $options = []) { if ($pdoOrDsn instanceof \PDO) { if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { @@ -181,7 +181,7 @@ class PdoSessionHandler extends AbstractSessionHandler /** * Adds the Table to the Schema if it doesn't exist. */ - public function configureSchema(Schema $schema, \Closure $isSameDatabase = null): void + public function configureSchema(Schema $schema, ?\Closure $isSameDatabase = null): void { if ($schema->hasTable($this->table) || ($isSameDatabase && !$isSameDatabase($this->getConnection()->exec(...)))) { return; diff --git a/lib/symfony/http-foundation/Session/Storage/MetadataBag.php b/lib/symfony/http-foundation/Session/Storage/MetadataBag.php index ebe4b748a..5bb4cfbc7 100644 --- a/lib/symfony/http-foundation/Session/Storage/MetadataBag.php +++ b/lib/symfony/http-foundation/Session/Storage/MetadataBag.php @@ -88,7 +88,7 @@ class MetadataBag implements SessionBagInterface * * @return void */ - public function stampNew(int $lifetime = null) + public function stampNew(?int $lifetime = null) { $this->stampCreated($lifetime); } @@ -139,7 +139,7 @@ class MetadataBag implements SessionBagInterface $this->name = $name; } - private function stampCreated(int $lifetime = null): void + private function stampCreated(?int $lifetime = null): void { $timeStamp = time(); $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; diff --git a/lib/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php b/lib/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php index d30b56d69..f02793d3e 100644 --- a/lib/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php +++ b/lib/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php @@ -62,7 +62,7 @@ class MockArraySessionStorage implements SessionStorageInterface */ protected $bags = []; - public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null) + public function __construct(string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) { $this->name = $name; $this->setMetadataBag($metaBag); @@ -91,7 +91,7 @@ class MockArraySessionStorage implements SessionStorageInterface return true; } - public function regenerate(bool $destroy = false, int $lifetime = null): bool + public function regenerate(bool $destroy = false, ?int $lifetime = null): bool { if (!$this->started) { $this->start(); @@ -192,7 +192,7 @@ class MockArraySessionStorage implements SessionStorageInterface /** * @return void */ - public function setMetadataBag(MetadataBag $bag = null) + public function setMetadataBag(?MetadataBag $bag = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -216,7 +216,7 @@ class MockArraySessionStorage implements SessionStorageInterface */ protected function generateId(): string { - return hash('sha256', uniqid('ss_mock_', true)); + return bin2hex(random_bytes(16)); } /** diff --git a/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php b/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php index 95f69f2e1..ef6d9d8f8 100644 --- a/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php +++ b/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php @@ -30,7 +30,7 @@ class MockFileSessionStorage extends MockArraySessionStorage /** * @param string|null $savePath Path of directory to save session files */ - public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) + public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) { $savePath ??= sys_get_temp_dir(); @@ -60,7 +60,7 @@ class MockFileSessionStorage extends MockArraySessionStorage return true; } - public function regenerate(bool $destroy = false, int $lifetime = null): bool + public function regenerate(bool $destroy = false, ?int $lifetime = null): bool { if (!$this->started) { $this->start(); diff --git a/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php b/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php index 8ecf943dc..6727cf14f 100644 --- a/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php +++ b/lib/symfony/http-foundation/Session/Storage/MockFileSessionStorageFactory.php @@ -28,7 +28,7 @@ class MockFileSessionStorageFactory implements SessionStorageFactoryInterface /** * @see MockFileSessionStorage constructor. */ - public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) + public function __construct(?string $savePath = null, string $name = 'MOCKSESSID', ?MetadataBag $metaBag = null) { $this->savePath = $savePath; $this->name = $name; diff --git a/lib/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/lib/symfony/http-foundation/Session/Storage/NativeSessionStorage.php index 7c6b6f929..f63de5740 100644 --- a/lib/symfony/http-foundation/Session/Storage/NativeSessionStorage.php +++ b/lib/symfony/http-foundation/Session/Storage/NativeSessionStorage.php @@ -89,7 +89,7 @@ class NativeSessionStorage implements SessionStorageInterface * trans_sid_hosts, $_SERVER['HTTP_HOST'] * trans_sid_tags, "a=href,area=href,frame=src,form=" */ - public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface $handler = null, MetadataBag $metaBag = null) + public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null) { if (!\extension_loaded('session')) { throw new \LogicException('PHP extension "session" is required.'); @@ -204,7 +204,7 @@ class NativeSessionStorage implements SessionStorageInterface $this->saveHandler->setName($name); } - public function regenerate(bool $destroy = false, int $lifetime = null): bool + public function regenerate(bool $destroy = false, ?int $lifetime = null): bool { // Cannot regenerate the session ID for non-active sessions. if (\PHP_SESSION_ACTIVE !== session_status()) { @@ -317,7 +317,7 @@ class NativeSessionStorage implements SessionStorageInterface /** * @return void */ - public function setMetadataBag(MetadataBag $metaBag = null) + public function setMetadataBag(?MetadataBag $metaBag = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -396,7 +396,7 @@ class NativeSessionStorage implements SessionStorageInterface * * @throws \InvalidArgumentException */ - public function setSaveHandler(AbstractProxy|\SessionHandlerInterface $saveHandler = null) + public function setSaveHandler(AbstractProxy|\SessionHandlerInterface|null $saveHandler = null) { if (1 > \func_num_args()) { trigger_deprecation('symfony/http-foundation', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -429,7 +429,7 @@ class NativeSessionStorage implements SessionStorageInterface * * @return void */ - protected function loadSession(array &$session = null) + protected function loadSession(?array &$session = null) { if (null === $session) { $session = &$_SESSION; diff --git a/lib/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php b/lib/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php index 08901284c..6463a4c1b 100644 --- a/lib/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php +++ b/lib/symfony/http-foundation/Session/Storage/NativeSessionStorageFactory.php @@ -30,7 +30,7 @@ class NativeSessionStorageFactory implements SessionStorageFactoryInterface /** * @see NativeSessionStorage constructor. */ - public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface $handler = null, MetadataBag $metaBag = null, bool $secure = false) + public function __construct(array $options = [], AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null, bool $secure = false) { $this->options = $options; $this->handler = $handler; diff --git a/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php b/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php index 28cb3c3d0..4fb26d2a9 100644 --- a/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php +++ b/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php @@ -20,7 +20,7 @@ use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; */ class PhpBridgeSessionStorage extends NativeSessionStorage { - public function __construct(AbstractProxy|\SessionHandlerInterface $handler = null, MetadataBag $metaBag = null) + public function __construct(AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null) { if (!\extension_loaded('session')) { throw new \LogicException('PHP extension "session" is required.'); diff --git a/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php b/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php index 5cc738024..aa4f800d3 100644 --- a/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php +++ b/lib/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorageFactory.php @@ -26,7 +26,7 @@ class PhpBridgeSessionStorageFactory implements SessionStorageFactoryInterface private ?MetadataBag $metaBag; private bool $secure; - public function __construct(AbstractProxy|\SessionHandlerInterface $handler = null, MetadataBag $metaBag = null, bool $secure = false) + public function __construct(AbstractProxy|\SessionHandlerInterface|null $handler = null, ?MetadataBag $metaBag = null, bool $secure = false) { $this->handler = $handler; $this->metaBag = $metaBag; diff --git a/lib/symfony/http-foundation/Session/Storage/SessionStorageInterface.php b/lib/symfony/http-foundation/Session/Storage/SessionStorageInterface.php index ed2189e4e..7865135b0 100644 --- a/lib/symfony/http-foundation/Session/Storage/SessionStorageInterface.php +++ b/lib/symfony/http-foundation/Session/Storage/SessionStorageInterface.php @@ -84,7 +84,7 @@ interface SessionStorageInterface * * @throws \RuntimeException If an error occurs while regenerating this storage */ - public function regenerate(bool $destroy = false, int $lifetime = null): bool; + public function regenerate(bool $destroy = false, ?int $lifetime = null): bool; /** * Force the session to be saved and closed. diff --git a/lib/symfony/http-foundation/StreamedResponse.php b/lib/symfony/http-foundation/StreamedResponse.php index 87be96a11..0ab88e098 100644 --- a/lib/symfony/http-foundation/StreamedResponse.php +++ b/lib/symfony/http-foundation/StreamedResponse.php @@ -33,7 +33,7 @@ class StreamedResponse extends Response /** * @param int $status The HTTP status code (200 "OK" by default) */ - public function __construct(callable $callback = null, int $status = 200, array $headers = []) + public function __construct(?callable $callback = null, int $status = 200, array $headers = []) { parent::__construct(null, $status, $headers); diff --git a/lib/symfony/http-foundation/composer.json b/lib/symfony/http-foundation/composer.json index be85696e5..732a011e9 100644 --- a/lib/symfony/http-foundation/composer.json +++ b/lib/symfony/http-foundation/composer.json @@ -24,7 +24,7 @@ "require-dev": { "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3|^7.0", + "symfony/cache": "^6.4.12|^7.1.5", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", "symfony/mime": "^5.4|^6.0|^7.0", @@ -32,7 +32,7 @@ "symfony/rate-limiter": "^5.4|^6.0|^7.0" }, "conflict": { - "symfony/cache": "<6.3" + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, diff --git a/lib/symfony/http-kernel/Attribute/MapQueryParameter.php b/lib/symfony/http-kernel/Attribute/MapQueryParameter.php index f83e331e4..bbc1fff27 100644 --- a/lib/symfony/http-kernel/Attribute/MapQueryParameter.php +++ b/lib/symfony/http-kernel/Attribute/MapQueryParameter.php @@ -22,7 +22,7 @@ use Symfony\Component\HttpKernel\Controller\ArgumentResolver\QueryParameterValue final class MapQueryParameter extends ValueResolver { /** - * @see https://php.net/filter.filters.validate for filter, flags and options + * @see https://php.net/manual/filter.constants for filter, flags and options * * @param string|null $name The name of the query parameter. If null, the name of the argument in the controller will be used. */ diff --git a/lib/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php b/lib/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php index a672956e0..47873fe18 100644 --- a/lib/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php +++ b/lib/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php @@ -31,7 +31,7 @@ class CacheWarmerAggregate implements CacheWarmerInterface /** * @param iterable $warmers */ - public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null) + public function __construct(iterable $warmers = [], bool $debug = false, ?string $deprecationLogsFilepath = null) { $this->warmers = $warmers; $this->debug = $debug; @@ -51,7 +51,7 @@ class CacheWarmerAggregate implements CacheWarmerInterface /** * @param string|null $buildDir */ - public function warmUp(string $cacheDir, string|SymfonyStyle $buildDir = null, SymfonyStyle $io = null): array + public function warmUp(string $cacheDir, string|SymfonyStyle|null $buildDir = null, ?SymfonyStyle $io = null): array { if ($buildDir instanceof SymfonyStyle) { trigger_deprecation('symfony/http-kernel', '6.4', 'Passing a "%s" as second argument of "%s()" is deprecated, pass it as third argument instead, after the build directory.', SymfonyStyle::class, __METHOD__); diff --git a/lib/symfony/http-kernel/Config/FileLocator.php b/lib/symfony/http-kernel/Config/FileLocator.php index f81f91925..fb6bb10f1 100644 --- a/lib/symfony/http-kernel/Config/FileLocator.php +++ b/lib/symfony/http-kernel/Config/FileLocator.php @@ -30,7 +30,7 @@ class FileLocator extends BaseFileLocator parent::__construct(); } - public function locate(string $file, string $currentPath = null, bool $first = true): string|array + public function locate(string $file, ?string $currentPath = null, bool $first = true): string|array { if (isset($file[0]) && '@' === $file[0]) { $resource = $this->kernel->locateResource($file); diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver.php index 6643cc58e..23c2d7faa 100644 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver.php +++ b/lib/symfony/http-kernel/Controller/ArgumentResolver.php @@ -39,14 +39,14 @@ final class ArgumentResolver implements ArgumentResolverInterface /** * @param iterable $argumentValueResolvers */ - public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [], ContainerInterface $namedResolvers = null) + public function __construct(?ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = [], ?ContainerInterface $namedResolvers = null) { $this->argumentMetadataFactory = $argumentMetadataFactory ?? new ArgumentMetadataFactory(); $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers(); $this->namedResolvers = $namedResolvers; } - public function getArguments(Request $request, callable $controller, \ReflectionFunctionAbstract $reflector = null): array + public function getArguments(Request $request, callable $controller, ?\ReflectionFunctionAbstract $reflector = null): array { $arguments = []; diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php index 444be1b3f..f0f735da4 100644 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php +++ b/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php @@ -40,11 +40,9 @@ use Symfony\Contracts\Translation\TranslatorInterface; class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscriberInterface { /** - * @see \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT * @see DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS */ private const CONTEXT_DENORMALIZE = [ - 'disable_type_enforcement' => true, 'collect_denormalization_errors' => true, ]; @@ -108,11 +106,15 @@ class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscr } catch (PartialDenormalizationException $e) { $trans = $this->translator ? $this->translator->trans(...) : fn ($m, $p) => strtr($m, $p); foreach ($e->getErrors() as $error) { - $parameters = ['{{ type }}' => implode('|', $error->getExpectedTypes())]; + $parameters = []; + $template = 'This value was of an unexpected type.'; + if ($expectedTypes = $error->getExpectedTypes()) { + $template = 'This value should be of type {{ type }}.'; + $parameters['{{ type }}'] = implode('|', $expectedTypes); + } if ($error->canUseMessageForUser()) { $parameters['hint'] = $error->getMessage(); } - $template = 'This value should be of type {{ type }}.'; $message = $trans($template, $parameters, 'validators'); $violations->add(new ConstraintViolation($message, $template, $parameters, null, $error->getPath(), null)); } @@ -161,7 +163,7 @@ class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscr return null; } - return $this->serializer->denormalize($data, $type, null, $attribute->serializationContext + self::CONTEXT_DENORMALIZE); + return $this->serializer->denormalize($data, $type, 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE); } private function mapRequestPayload(Request $request, string $type, MapRequestPayload $attribute): ?object @@ -175,7 +177,7 @@ class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscr } if ($data = $request->request->all()) { - return $this->serializer->denormalize($data, $type, null, $attribute->serializationContext + self::CONTEXT_DENORMALIZE); + return $this->serializer->denormalize($data, $type, 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE); } if ('' === $data = $request->getContent()) { diff --git a/lib/symfony/http-kernel/Controller/ContainerControllerResolver.php b/lib/symfony/http-kernel/Controller/ContainerControllerResolver.php index 1c9254e73..12232d58b 100644 --- a/lib/symfony/http-kernel/Controller/ContainerControllerResolver.php +++ b/lib/symfony/http-kernel/Controller/ContainerControllerResolver.php @@ -25,7 +25,7 @@ class ContainerControllerResolver extends ControllerResolver { protected $container; - public function __construct(ContainerInterface $container, LoggerInterface $logger = null) + public function __construct(ContainerInterface $container, ?LoggerInterface $logger = null) { $this->container = $container; diff --git a/lib/symfony/http-kernel/Controller/ControllerResolver.php b/lib/symfony/http-kernel/Controller/ControllerResolver.php index d39508949..8424b02cc 100644 --- a/lib/symfony/http-kernel/Controller/ControllerResolver.php +++ b/lib/symfony/http-kernel/Controller/ControllerResolver.php @@ -29,7 +29,7 @@ class ControllerResolver implements ControllerResolverInterface private array $allowedControllerTypes = []; private array $allowedControllerAttributes = [AsController::class => AsController::class]; - public function __construct(LoggerInterface $logger = null) + public function __construct(?LoggerInterface $logger = null) { $this->logger = $logger; } @@ -240,7 +240,7 @@ class ControllerResolver implements ControllerResolverInterface $r = new \ReflectionFunction($controller); $name = $r->name; - if (str_contains($name, '{closure}')) { + if (str_contains($name, '{closure')) { $name = $class = \Closure::class; } elseif ($class = \PHP_VERSION_ID >= 80111 ? $r->getClosureCalledClass() : $r->getClosureScopeClass()) { $class = $class->name; @@ -265,7 +265,7 @@ class ControllerResolver implements ControllerResolverInterface } if (str_contains($name, '@anonymous')) { - $name = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $name); + $name = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)?[0-9a-fA-F]++/', fn ($m) => class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0], $name); } if (-1 === $request->attributes->get('_check_controller_is_allowed')) { diff --git a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php b/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php index a352090ea..dd6c8be86 100644 --- a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php +++ b/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php @@ -106,7 +106,7 @@ class ArgumentMetadata * * @return array */ - public function getAttributes(string $name = null, int $flags = 0): array + public function getAttributes(?string $name = null, int $flags = 0): array { if (!$name) { return $this->attributes; diff --git a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php b/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php index cb7f0a78c..7eafdc94b 100644 --- a/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php +++ b/lib/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php @@ -18,7 +18,7 @@ namespace Symfony\Component\HttpKernel\ControllerMetadata; */ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface { - public function createArgumentMetadata(string|object|array $controller, \ReflectionFunctionAbstract $reflector = null): array + public function createArgumentMetadata(string|object|array $controller, ?\ReflectionFunctionAbstract $reflector = null): array { $arguments = []; $reflector ??= new \ReflectionFunction($controller(...)); diff --git a/lib/symfony/http-kernel/DataCollector/AjaxDataCollector.php b/lib/symfony/http-kernel/DataCollector/AjaxDataCollector.php index 016ef2ece..3c8d2f0f6 100644 --- a/lib/symfony/http-kernel/DataCollector/AjaxDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/AjaxDataCollector.php @@ -21,7 +21,7 @@ use Symfony\Component\HttpFoundation\Response; */ class AjaxDataCollector extends DataCollector { - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { // all collecting is done client side } diff --git a/lib/symfony/http-kernel/DataCollector/ConfigDataCollector.php b/lib/symfony/http-kernel/DataCollector/ConfigDataCollector.php index 8a75227d4..f9ca5da1d 100644 --- a/lib/symfony/http-kernel/DataCollector/ConfigDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/ConfigDataCollector.php @@ -30,7 +30,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte /** * Sets the Kernel associated with this Request. */ - public function setKernel(KernelInterface $kernel = null): void + public function setKernel(?KernelInterface $kernel = null): void { if (1 > \func_num_args()) { trigger_deprecation('symfony/http-kernel', '6.2', 'Calling "%s()" without any arguments is deprecated, pass null explicitly instead.', __METHOD__); @@ -39,7 +39,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte $this->kernel = $kernel; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { $eom = \DateTimeImmutable::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_MAINTENANCE); $eol = \DateTimeImmutable::createFromFormat('d/m/Y', '01/'.Kernel::END_OF_LIFE); diff --git a/lib/symfony/http-kernel/DataCollector/DataCollector.php b/lib/symfony/http-kernel/DataCollector/DataCollector.php index d8b795d42..fdc73de06 100644 --- a/lib/symfony/http-kernel/DataCollector/DataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/DataCollector.php @@ -63,9 +63,21 @@ abstract class DataCollector implements DataCollectorInterface $casters = [ '*' => function ($v, array $a, Stub $s, $isNested) { if (!$v instanceof Stub) { + $b = $a; foreach ($a as $k => $v) { - if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) { - $a[$k] = new CutStub($v); + if (!\is_object($v) || $v instanceof \DateTimeInterface || $v instanceof Stub) { + continue; + } + + try { + $a[$k] = $s = new CutStub($v); + + if ($b[$k] === $s) { + // we've hit a non-typed reference + $a[$k] = $v; + } + } catch (\TypeError $e) { + // we've hit a typed reference } } } diff --git a/lib/symfony/http-kernel/DataCollector/DataCollectorInterface.php b/lib/symfony/http-kernel/DataCollector/DataCollectorInterface.php index 8df94ccb8..5e8593d07 100644 --- a/lib/symfony/http-kernel/DataCollector/DataCollectorInterface.php +++ b/lib/symfony/http-kernel/DataCollector/DataCollectorInterface.php @@ -27,7 +27,7 @@ interface DataCollectorInterface extends ResetInterface * * @return void */ - public function collect(Request $request, Response $response, \Throwable $exception = null); + public function collect(Request $request, Response $response, ?\Throwable $exception = null); /** * Returns the name of the collector. diff --git a/lib/symfony/http-kernel/DataCollector/DumpDataCollector.php b/lib/symfony/http-kernel/DataCollector/DumpDataCollector.php index ce02b545b..0a46a8cd4 100644 --- a/lib/symfony/http-kernel/DataCollector/DumpDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/DumpDataCollector.php @@ -44,7 +44,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface private mixed $sourceContextProvider; private bool $webMode; - public function __construct(Stopwatch $stopwatch = null, string|FileLinkFormatter $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, DataDumperInterface|Connection $dumper = null, bool $webMode = null) + public function __construct(?Stopwatch $stopwatch = null, string|FileLinkFormatter|null $fileLinkFormat = null, ?string $charset = null, ?RequestStack $requestStack = null, DataDumperInterface|Connection|null $dumper = null, ?bool $webMode = null) { $fileLinkFormat = $fileLinkFormat ?: \ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); $this->stopwatch = $stopwatch; @@ -100,7 +100,7 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface return null; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { if (!$this->dataCount) { $this->data = []; diff --git a/lib/symfony/http-kernel/DataCollector/EventDataCollector.php b/lib/symfony/http-kernel/DataCollector/EventDataCollector.php index a6524ea04..3a94dbc32 100644 --- a/lib/symfony/http-kernel/DataCollector/EventDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/EventDataCollector.php @@ -36,7 +36,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter * @param iterable|EventDispatcherInterface|null $dispatchers */ public function __construct( - iterable|EventDispatcherInterface $dispatchers = null, + iterable|EventDispatcherInterface|null $dispatchers = null, private ?RequestStack $requestStack = null, private string $defaultDispatcher = 'event_dispatcher', ) { @@ -46,7 +46,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter $this->dispatchers = $dispatchers ?? []; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { $this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null; $this->data = []; @@ -86,7 +86,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter /** * @see TraceableEventDispatcher */ - public function setCalledListeners(array $listeners, string $dispatcher = null): void + public function setCalledListeners(array $listeners, ?string $dispatcher = null): void { $this->data[$dispatcher ?? $this->defaultDispatcher]['called_listeners'] = $listeners; } @@ -94,7 +94,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter /** * @see TraceableEventDispatcher */ - public function getCalledListeners(string $dispatcher = null): array|Data + public function getCalledListeners(?string $dispatcher = null): array|Data { return $this->data[$dispatcher ?? $this->defaultDispatcher]['called_listeners'] ?? []; } @@ -102,7 +102,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter /** * @see TraceableEventDispatcher */ - public function setNotCalledListeners(array $listeners, string $dispatcher = null): void + public function setNotCalledListeners(array $listeners, ?string $dispatcher = null): void { $this->data[$dispatcher ?? $this->defaultDispatcher]['not_called_listeners'] = $listeners; } @@ -110,7 +110,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter /** * @see TraceableEventDispatcher */ - public function getNotCalledListeners(string $dispatcher = null): array|Data + public function getNotCalledListeners(?string $dispatcher = null): array|Data { return $this->data[$dispatcher ?? $this->defaultDispatcher]['not_called_listeners'] ?? []; } @@ -120,7 +120,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter * * @see TraceableEventDispatcher */ - public function setOrphanedEvents(array $events, string $dispatcher = null): void + public function setOrphanedEvents(array $events, ?string $dispatcher = null): void { $this->data[$dispatcher ?? $this->defaultDispatcher]['orphaned_events'] = $events; } @@ -128,7 +128,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter /** * @see TraceableEventDispatcher */ - public function getOrphanedEvents(string $dispatcher = null): array|Data + public function getOrphanedEvents(?string $dispatcher = null): array|Data { return $this->data[$dispatcher ?? $this->defaultDispatcher]['orphaned_events'] ?? []; } diff --git a/lib/symfony/http-kernel/DataCollector/ExceptionDataCollector.php b/lib/symfony/http-kernel/DataCollector/ExceptionDataCollector.php index 16a29adc1..80156bc8d 100644 --- a/lib/symfony/http-kernel/DataCollector/ExceptionDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/ExceptionDataCollector.php @@ -22,7 +22,7 @@ use Symfony\Component\HttpFoundation\Response; */ class ExceptionDataCollector extends DataCollector { - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { if (null !== $exception) { $this->data = [ diff --git a/lib/symfony/http-kernel/DataCollector/LoggerDataCollector.php b/lib/symfony/http-kernel/DataCollector/LoggerDataCollector.php index eb2b9c85c..cf17e7a73 100644 --- a/lib/symfony/http-kernel/DataCollector/LoggerDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/LoggerDataCollector.php @@ -32,14 +32,14 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte private ?RequestStack $requestStack; private ?array $processedLogs = null; - public function __construct(object $logger = null, string $containerPathPrefix = null, RequestStack $requestStack = null) + public function __construct(?object $logger = null, ?string $containerPathPrefix = null, ?RequestStack $requestStack = null) { $this->logger = DebugLoggerConfigurator::getDebugLogger($logger); $this->containerPathPrefix = $containerPathPrefix; $this->requestStack = $requestStack; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { $this->currentRequest = $this->requestStack && $this->requestStack->getMainRequest() !== $request ? $request : null; } @@ -199,7 +199,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte return $logs; } - private function getContainerCompilerLogs(string $compilerLogsFilepath = null): array + private function getContainerCompilerLogs(?string $compilerLogsFilepath = null): array { if (!$compilerLogsFilepath || !is_file($compilerLogsFilepath)) { return []; diff --git a/lib/symfony/http-kernel/DataCollector/MemoryDataCollector.php b/lib/symfony/http-kernel/DataCollector/MemoryDataCollector.php index 8b8894367..9715f94ee 100644 --- a/lib/symfony/http-kernel/DataCollector/MemoryDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/MemoryDataCollector.php @@ -26,7 +26,7 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte $this->reset(); } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { $this->updateMemoryUsage(); } diff --git a/lib/symfony/http-kernel/DataCollector/RequestDataCollector.php b/lib/symfony/http-kernel/DataCollector/RequestDataCollector.php index eae5f24b7..12951b495 100644 --- a/lib/symfony/http-kernel/DataCollector/RequestDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/RequestDataCollector.php @@ -38,13 +38,13 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter private array $sessionUsages = []; private ?RequestStack $requestStack; - public function __construct(RequestStack $requestStack = null) + public function __construct(?RequestStack $requestStack = null) { $this->controllers = new \SplObjectStorage(); $this->requestStack = $requestStack; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { // attributes are serialized and as they can be anything, they need to be converted to strings. $attributes = []; @@ -63,7 +63,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter $sessionMetadata = []; $sessionAttributes = []; $flashes = []; - if ($request->hasSession()) { + if (!$request->attributes->getBoolean('_stateless') && $request->hasSession()) { $session = $request->getSession(); if ($session->isStarted()) { $sessionMetadata['Created'] = date(\DATE_RFC822, $session->getMetadataBag()->getCreated()); @@ -505,7 +505,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter 'line' => $r->getStartLine(), ]; - if (str_contains($r->name, '{closure}')) { + if (str_contains($r->name, '{closure')) { return $controller; } $controller['method'] = $r->name; diff --git a/lib/symfony/http-kernel/DataCollector/RouterDataCollector.php b/lib/symfony/http-kernel/DataCollector/RouterDataCollector.php index 444138da7..4d91fd6e1 100644 --- a/lib/symfony/http-kernel/DataCollector/RouterDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/RouterDataCollector.php @@ -34,7 +34,7 @@ class RouterDataCollector extends DataCollector /** * @final */ - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { if ($response instanceof RedirectResponse) { $this->data['redirect'] = true; diff --git a/lib/symfony/http-kernel/DataCollector/TimeDataCollector.php b/lib/symfony/http-kernel/DataCollector/TimeDataCollector.php index a8b7ead94..9799a1333 100644 --- a/lib/symfony/http-kernel/DataCollector/TimeDataCollector.php +++ b/lib/symfony/http-kernel/DataCollector/TimeDataCollector.php @@ -27,14 +27,14 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf private ?KernelInterface $kernel; private ?Stopwatch $stopwatch; - public function __construct(KernelInterface $kernel = null, Stopwatch $stopwatch = null) + public function __construct(?KernelInterface $kernel = null, ?Stopwatch $stopwatch = null) { $this->kernel = $kernel; $this->stopwatch = $stopwatch; $this->data = ['events' => [], 'stopwatch_installed' => false, 'start_time' => 0]; } - public function collect(Request $request, Response $response, \Throwable $exception = null): void + public function collect(Request $request, Response $response, ?\Throwable $exception = null): void { if (null !== $this->kernel) { $startTime = $this->kernel->getStartTime(); diff --git a/lib/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php b/lib/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php index 49f188c22..5b3e1cddd 100644 --- a/lib/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php +++ b/lib/symfony/http-kernel/Debug/ErrorHandlerConfigurator.php @@ -36,7 +36,7 @@ class ErrorHandlerConfigurator * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged * @param bool $scope Enables/disables scoping mode */ - public function __construct(LoggerInterface $logger = null, array|int|null $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, bool $scope = true, LoggerInterface $deprecationLogger = null) + public function __construct(?LoggerInterface $logger = null, array|int|null $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, bool $scope = true, ?LoggerInterface $deprecationLogger = null) { $this->logger = $logger; $this->levels = $levels ?? \E_ALL; diff --git a/lib/symfony/http-kernel/Debug/TraceableEventDispatcher.php b/lib/symfony/http-kernel/Debug/TraceableEventDispatcher.php index d31ce7581..f3101d5b1 100644 --- a/lib/symfony/http-kernel/Debug/TraceableEventDispatcher.php +++ b/lib/symfony/http-kernel/Debug/TraceableEventDispatcher.php @@ -66,7 +66,11 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher if (null === $sectionId) { break; } - $this->stopwatch->stopSection($sectionId); + try { + $this->stopwatch->stopSection($sectionId); + } catch (\LogicException) { + // The stop watch service might have been reset in the meantime + } break; case KernelEvents::TERMINATE: // In the special case described in the `preDispatch` method above, the `$token` section diff --git a/lib/symfony/http-kernel/DependencyInjection/LoggerPass.php b/lib/symfony/http-kernel/DependencyInjection/LoggerPass.php index 6270875be..0061a577c 100644 --- a/lib/symfony/http-kernel/DependencyInjection/LoggerPass.php +++ b/lib/symfony/http-kernel/DependencyInjection/LoggerPass.php @@ -30,7 +30,9 @@ class LoggerPass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { - $container->setAlias(LoggerInterface::class, 'logger'); + if (!$container->has(LoggerInterface::class)) { + $container->setAlias(LoggerInterface::class, 'logger'); + } if ($container->has('logger')) { return; diff --git a/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index f2cf2422b..7d13c223a 100644 --- a/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -45,6 +45,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface $parameterBag = $container->getParameterBag(); $controllers = []; + $controllerClasses = []; $publicAliases = []; foreach ($container->getAliases() as $id => $alias) { @@ -58,6 +59,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface foreach ($container->findTaggedServiceIds('controller.service_arguments', true) as $id => $tags) { $def = $container->getDefinition($id); $def->setPublic(true); + $def->setLazy(false); $class = $def->getClass(); $autowire = $def->isAutowired(); $bindings = $def->getBindings(); @@ -74,6 +76,8 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } + $controllerClasses[] = $class; + // get regular public methods $methods = []; $arguments = []; @@ -155,7 +159,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface continue; } elseif (!$autowire || (!($autowireAttributes ??= $p->getAttributes(Autowire::class, \ReflectionAttribute::IS_INSTANCEOF)) && (!$type || '\\' !== $target[0]))) { continue; - } elseif (is_subclass_of($type, \UnitEnum::class)) { + } elseif (!$autowireAttributes && is_subclass_of($type, \UnitEnum::class)) { // do not attempt to register enum typed arguments if not already present in bindings continue; } elseif (!$p->allowsNull()) { @@ -227,5 +231,10 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface } $container->setAlias('argument_resolver.controller_locator', (string) $controllerLocatorRef); + + if ($container->hasDefinition('controller_resolver')) { + $container->getDefinition('controller_resolver') + ->addMethodCall('allowControllers', [array_unique($controllerClasses)]); + } } } diff --git a/lib/symfony/http-kernel/Event/ControllerArgumentsEvent.php b/lib/symfony/http-kernel/Event/ControllerArgumentsEvent.php index c90b7706f..4c804ccf1 100644 --- a/lib/symfony/http-kernel/Event/ControllerArgumentsEvent.php +++ b/lib/symfony/http-kernel/Event/ControllerArgumentsEvent.php @@ -52,7 +52,7 @@ final class ControllerArgumentsEvent extends KernelEvent /** * @param array>|null $attributes */ - public function setController(callable $controller, array $attributes = null): void + public function setController(callable $controller, ?array $attributes = null): void { $this->controllerEvent->setController($controller, $attributes); unset($this->namedArguments); @@ -102,7 +102,7 @@ final class ControllerArgumentsEvent extends KernelEvent * * @psalm-return (T is null ? array> : list) */ - public function getAttributes(string $className = null): array + public function getAttributes(?string $className = null): array { return $this->controllerEvent->getAttributes($className); } diff --git a/lib/symfony/http-kernel/Event/ControllerEvent.php b/lib/symfony/http-kernel/Event/ControllerEvent.php index 239b00512..6db2c15f9 100644 --- a/lib/symfony/http-kernel/Event/ControllerEvent.php +++ b/lib/symfony/http-kernel/Event/ControllerEvent.php @@ -51,7 +51,7 @@ final class ControllerEvent extends KernelEvent /** * @param array>|null $attributes */ - public function setController(callable $controller, array $attributes = null): void + public function setController(callable $controller, ?array $attributes = null): void { if (null !== $attributes) { $this->attributes = $attributes; @@ -70,7 +70,7 @@ final class ControllerEvent extends KernelEvent if (\is_array($controller) && method_exists(...$controller)) { $this->controllerReflector = new \ReflectionMethod(...$controller); } elseif (\is_string($controller) && str_contains($controller, '::')) { - $this->controllerReflector = new \ReflectionMethod($controller); + $this->controllerReflector = new \ReflectionMethod(...explode('::', $controller, 2)); } else { $this->controllerReflector = new \ReflectionFunction($controller(...)); } @@ -87,7 +87,7 @@ final class ControllerEvent extends KernelEvent * * @psalm-return (T is null ? array> : list) */ - public function getAttributes(string $className = null): array + public function getAttributes(?string $className = null): array { if (isset($this->attributes)) { return null === $className ? $this->attributes : $this->attributes[$className] ?? []; @@ -98,7 +98,7 @@ final class ControllerEvent extends KernelEvent } elseif (\is_string($this->controller) && false !== $i = strpos($this->controller, '::')) { $class = new \ReflectionClass(substr($this->controller, 0, $i)); } else { - $class = str_contains($this->controllerReflector->name, '{closure}') ? null : (\PHP_VERSION_ID >= 80111 ? $this->controllerReflector->getClosureCalledClass() : $this->controllerReflector->getClosureScopeClass()); + $class = str_contains($this->controllerReflector->name, '{closure') ? null : (\PHP_VERSION_ID >= 80111 ? $this->controllerReflector->getClosureCalledClass() : $this->controllerReflector->getClosureScopeClass()); } $this->attributes = []; diff --git a/lib/symfony/http-kernel/Event/KernelEvent.php b/lib/symfony/http-kernel/Event/KernelEvent.php index e64cc419b..02426c52a 100644 --- a/lib/symfony/http-kernel/Event/KernelEvent.php +++ b/lib/symfony/http-kernel/Event/KernelEvent.php @@ -16,7 +16,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Contracts\EventDispatcher\Event; /** - * Base class for events thrown in the HttpKernel component. + * Base class for events dispatched in the HttpKernel component. * * @author Bernhard Schussek */ diff --git a/lib/symfony/http-kernel/Event/ViewEvent.php b/lib/symfony/http-kernel/Event/ViewEvent.php index bf96985b2..4d963aea1 100644 --- a/lib/symfony/http-kernel/Event/ViewEvent.php +++ b/lib/symfony/http-kernel/Event/ViewEvent.php @@ -28,7 +28,7 @@ final class ViewEvent extends RequestEvent public readonly ?ControllerArgumentsEvent $controllerArgumentsEvent; private mixed $controllerResult; - public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, mixed $controllerResult, ControllerArgumentsEvent $controllerArgumentsEvent = null) + public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, mixed $controllerResult, ?ControllerArgumentsEvent $controllerArgumentsEvent = null) { parent::__construct($kernel, $request, $requestType); diff --git a/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php b/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php index 2f012ab52..1ce490537 100644 --- a/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php +++ b/lib/symfony/http-kernel/EventListener/AbstractSessionListener.php @@ -55,7 +55,7 @@ abstract class AbstractSessionListener implements EventSubscriberInterface, Rese /** * @internal */ - public function __construct(ContainerInterface $container = null, bool $debug = false, array $sessionOptions = []) + public function __construct(?ContainerInterface $container = null, bool $debug = false, array $sessionOptions = []) { $this->container = $container; $this->debug = $debug; diff --git a/lib/symfony/http-kernel/EventListener/DebugHandlersListener.php b/lib/symfony/http-kernel/EventListener/DebugHandlersListener.php index ce746bd12..ee720b1ea 100644 --- a/lib/symfony/http-kernel/EventListener/DebugHandlersListener.php +++ b/lib/symfony/http-kernel/EventListener/DebugHandlersListener.php @@ -41,13 +41,14 @@ class DebugHandlersListener implements EventSubscriberInterface * @param bool $webMode * @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception */ - public function __construct(callable $exceptionHandler = null, bool|LoggerInterface $webMode = null) + public function __construct(?callable $exceptionHandler = null, bool|LoggerInterface|null $webMode = null) { if ($webMode instanceof LoggerInterface) { // BC with Symfony 5 $webMode = null; } - $handler = set_exception_handler('is_int'); + + $handler = set_exception_handler('var_dump'); $this->earlyHandler = \is_array($handler) ? $handler[0] : null; restore_exception_handler(); @@ -58,7 +59,7 @@ class DebugHandlersListener implements EventSubscriberInterface /** * Configures the error handler. */ - public function configure(object $event = null): void + public function configure(?object $event = null): void { if ($event instanceof ConsoleEvent && $this->webMode) { return; @@ -67,6 +68,7 @@ class DebugHandlersListener implements EventSubscriberInterface return; } $this->firstCall = $this->hasTerminatedWithException = false; + $hasRun = null; if (!$this->exceptionHandler) { if ($event instanceof KernelEvent) { @@ -93,7 +95,7 @@ class DebugHandlersListener implements EventSubscriberInterface } } if ($this->exceptionHandler) { - $handler = set_exception_handler(static fn () => null); + $handler = set_exception_handler('var_dump'); $handler = \is_array($handler) ? $handler[0] : null; restore_exception_handler(); @@ -103,6 +105,19 @@ class DebugHandlersListener implements EventSubscriberInterface if ($handler instanceof ErrorHandler) { $handler->setExceptionHandler($this->exceptionHandler); + if (null !== $hasRun) { + $throwAt = $handler->throwAt(0) | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR | \E_USER_ERROR | \E_RECOVERABLE_ERROR | \E_PARSE; + $loggers = []; + + foreach ($handler->setLoggers([]) as $type => $log) { + if ($type & $throwAt) { + $loggers[$type] = [null, $log[1]]; + } + } + + // Assume $kernel->terminateWithException() will log uncaught exceptions appropriately + $handler->setLoggers($loggers); + } } $this->exceptionHandler = null; } diff --git a/lib/symfony/http-kernel/EventListener/DumpListener.php b/lib/symfony/http-kernel/EventListener/DumpListener.php index b10bd37f4..07a4e7e6a 100644 --- a/lib/symfony/http-kernel/EventListener/DumpListener.php +++ b/lib/symfony/http-kernel/EventListener/DumpListener.php @@ -29,7 +29,7 @@ class DumpListener implements EventSubscriberInterface private DataDumperInterface $dumper; private ?Connection $connection; - public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null) + public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, ?Connection $connection = null) { $this->cloner = $cloner; $this->dumper = $dumper; @@ -45,7 +45,7 @@ class DumpListener implements EventSubscriberInterface $dumper = $this->dumper; $connection = $this->connection; - VarDumper::setHandler(static function ($var, string $label = null) use ($cloner, $dumper, $connection) { + VarDumper::setHandler(static function ($var, ?string $label = null) use ($cloner, $dumper, $connection) { $data = $cloner->cloneVar($var); if (null !== $label) { $data = $data->withContext(['label' => $label]); diff --git a/lib/symfony/http-kernel/EventListener/ErrorListener.php b/lib/symfony/http-kernel/EventListener/ErrorListener.php index a2f6db57a..7aa4875e5 100644 --- a/lib/symfony/http-kernel/EventListener/ErrorListener.php +++ b/lib/symfony/http-kernel/EventListener/ErrorListener.php @@ -44,7 +44,7 @@ class ErrorListener implements EventSubscriberInterface /** * @param array|null}> $exceptionsMapping */ - public function __construct(string|object|array|null $controller, LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = []) + public function __construct(string|object|array|null $controller, ?LoggerInterface $logger = null, bool $debug = false, array $exceptionsMapping = []) { $this->controller = $controller; $this->logger = $logger; @@ -104,11 +104,11 @@ class ErrorListener implements EventSubscriberInterface $throwable = $event->getThrowable(); - if ($exceptionHandler = set_exception_handler(var_dump(...))) { - restore_exception_handler(); - if (\is_array($exceptionHandler) && $exceptionHandler[0] instanceof ErrorHandler) { - $throwable = $exceptionHandler[0]->enhanceError($event->getThrowable()); - } + $exceptionHandler = set_exception_handler('var_dump'); + restore_exception_handler(); + + if (\is_array($exceptionHandler) && $exceptionHandler[0] instanceof ErrorHandler) { + $throwable = $exceptionHandler[0]->enhanceError($event->getThrowable()); } $request = $this->duplicateRequest($throwable, $event->getRequest()); @@ -183,7 +183,7 @@ class ErrorListener implements EventSubscriberInterface /** * Logs an exception. */ - protected function logException(\Throwable $exception, string $message, string $logLevel = null): void + protected function logException(\Throwable $exception, string $message, ?string $logLevel = null): void { if (null === $this->logger) { return; diff --git a/lib/symfony/http-kernel/EventListener/LocaleListener.php b/lib/symfony/http-kernel/EventListener/LocaleListener.php index 65a3bfde4..9feaa0b4f 100644 --- a/lib/symfony/http-kernel/EventListener/LocaleListener.php +++ b/lib/symfony/http-kernel/EventListener/LocaleListener.php @@ -35,7 +35,7 @@ class LocaleListener implements EventSubscriberInterface private bool $useAcceptLanguageHeader; private array $enabledLocales; - public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = false, array $enabledLocales = []) + public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', ?RequestContextAwareInterface $router = null, bool $useAcceptLanguageHeader = false, array $enabledLocales = []) { $this->defaultLocale = $defaultLocale; $this->requestStack = $requestStack; diff --git a/lib/symfony/http-kernel/EventListener/ProfilerListener.php b/lib/symfony/http-kernel/EventListener/ProfilerListener.php index 716d939fd..1f30582f4 100644 --- a/lib/symfony/http-kernel/EventListener/ProfilerListener.php +++ b/lib/symfony/http-kernel/EventListener/ProfilerListener.php @@ -48,7 +48,7 @@ class ProfilerListener implements EventSubscriberInterface * @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise * @param bool $onlyMainRequests True if the profiler only collects data when the request is the main request, false otherwise */ - public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false, string $collectParameter = null) + public function __construct(Profiler $profiler, RequestStack $requestStack, ?RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMainRequests = false, ?string $collectParameter = null) { $this->profiler = $profiler; $this->matcher = $matcher; @@ -97,7 +97,7 @@ class ProfilerListener implements EventSubscriberInterface return; } - $session = $request->hasPreviousSession() ? $request->getSession() : null; + $session = !$request->attributes->getBoolean('_stateless') && $request->hasPreviousSession() ? $request->getSession() : null; if ($session instanceof Session) { $usageIndexValue = $usageIndexReference = &$session->getUsageIndex(); diff --git a/lib/symfony/http-kernel/EventListener/RouterListener.php b/lib/symfony/http-kernel/EventListener/RouterListener.php index bb393c779..f4406ade4 100644 --- a/lib/symfony/http-kernel/EventListener/RouterListener.php +++ b/lib/symfony/http-kernel/EventListener/RouterListener.php @@ -53,7 +53,7 @@ class RouterListener implements EventSubscriberInterface * * @throws \InvalidArgumentException */ - public function __construct(UrlMatcherInterface|RequestMatcherInterface $matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, string $projectDir = null, bool $debug = true) + public function __construct(UrlMatcherInterface|RequestMatcherInterface $matcher, RequestStack $requestStack, ?RequestContext $context = null, ?LoggerInterface $logger = null, ?string $projectDir = null, bool $debug = true) { if (null === $context && !$matcher instanceof RequestContextAwareInterface) { throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.'); diff --git a/lib/symfony/http-kernel/EventListener/SurrogateListener.php b/lib/symfony/http-kernel/EventListener/SurrogateListener.php index 17bdf2b39..a702a68f8 100644 --- a/lib/symfony/http-kernel/EventListener/SurrogateListener.php +++ b/lib/symfony/http-kernel/EventListener/SurrogateListener.php @@ -28,7 +28,7 @@ class SurrogateListener implements EventSubscriberInterface { private ?SurrogateInterface $surrogate; - public function __construct(SurrogateInterface $surrogate = null) + public function __construct(?SurrogateInterface $surrogate = null) { $this->surrogate = $surrogate; } diff --git a/lib/symfony/http-kernel/Exception/AccessDeniedHttpException.php b/lib/symfony/http-kernel/Exception/AccessDeniedHttpException.php index 78e8fe37d..0f9ea715c 100644 --- a/lib/symfony/http-kernel/Exception/AccessDeniedHttpException.php +++ b/lib/symfony/http-kernel/Exception/AccessDeniedHttpException.php @@ -17,7 +17,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class AccessDeniedHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(403, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/BadRequestHttpException.php b/lib/symfony/http-kernel/Exception/BadRequestHttpException.php index c920fbd0d..57a7a2583 100644 --- a/lib/symfony/http-kernel/Exception/BadRequestHttpException.php +++ b/lib/symfony/http-kernel/Exception/BadRequestHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class BadRequestHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(400, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/ConflictHttpException.php b/lib/symfony/http-kernel/Exception/ConflictHttpException.php index a5a6f8405..997c4a681 100644 --- a/lib/symfony/http-kernel/Exception/ConflictHttpException.php +++ b/lib/symfony/http-kernel/Exception/ConflictHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class ConflictHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(409, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/GoneHttpException.php b/lib/symfony/http-kernel/Exception/GoneHttpException.php index 2893f05cb..c40d597cc 100644 --- a/lib/symfony/http-kernel/Exception/GoneHttpException.php +++ b/lib/symfony/http-kernel/Exception/GoneHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class GoneHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(410, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/HttpException.php b/lib/symfony/http-kernel/Exception/HttpException.php index e12abce00..6d2c253a3 100644 --- a/lib/symfony/http-kernel/Exception/HttpException.php +++ b/lib/symfony/http-kernel/Exception/HttpException.php @@ -21,7 +21,7 @@ class HttpException extends \RuntimeException implements HttpExceptionInterface private int $statusCode; private array $headers; - public function __construct(int $statusCode, string $message = '', \Throwable $previous = null, array $headers = [], int $code = 0) + public function __construct(int $statusCode, string $message = '', ?\Throwable $previous = null, array $headers = [], int $code = 0) { $this->statusCode = $statusCode; $this->headers = $headers; diff --git a/lib/symfony/http-kernel/Exception/LengthRequiredHttpException.php b/lib/symfony/http-kernel/Exception/LengthRequiredHttpException.php index a3dd8b3cd..ca8741e40 100644 --- a/lib/symfony/http-kernel/Exception/LengthRequiredHttpException.php +++ b/lib/symfony/http-kernel/Exception/LengthRequiredHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class LengthRequiredHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(411, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/LockedHttpException.php b/lib/symfony/http-kernel/Exception/LockedHttpException.php index 069619bfc..3f05c2277 100644 --- a/lib/symfony/http-kernel/Exception/LockedHttpException.php +++ b/lib/symfony/http-kernel/Exception/LockedHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class LockedHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(423, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php b/lib/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php index cfbaf5cb0..33572e461 100644 --- a/lib/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php +++ b/lib/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php @@ -19,7 +19,7 @@ class MethodNotAllowedHttpException extends HttpException /** * @param string[] $allow An array of allowed methods */ - public function __construct(array $allow, string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(array $allow, string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { $headers['Allow'] = strtoupper(implode(', ', $allow)); diff --git a/lib/symfony/http-kernel/Exception/NotAcceptableHttpException.php b/lib/symfony/http-kernel/Exception/NotAcceptableHttpException.php index ec2bb596f..13e9c2312 100644 --- a/lib/symfony/http-kernel/Exception/NotAcceptableHttpException.php +++ b/lib/symfony/http-kernel/Exception/NotAcceptableHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class NotAcceptableHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(406, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/NotFoundHttpException.php b/lib/symfony/http-kernel/Exception/NotFoundHttpException.php index 0e78fcc15..e1b489eed 100644 --- a/lib/symfony/http-kernel/Exception/NotFoundHttpException.php +++ b/lib/symfony/http-kernel/Exception/NotFoundHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class NotFoundHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(404, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/PreconditionFailedHttpException.php b/lib/symfony/http-kernel/Exception/PreconditionFailedHttpException.php index 4431f89d0..8ec710e41 100644 --- a/lib/symfony/http-kernel/Exception/PreconditionFailedHttpException.php +++ b/lib/symfony/http-kernel/Exception/PreconditionFailedHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class PreconditionFailedHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(412, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php b/lib/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php index f75afd370..848876939 100644 --- a/lib/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php +++ b/lib/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php @@ -18,7 +18,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class PreconditionRequiredHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(428, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php b/lib/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php index d4862bd10..842271dc9 100644 --- a/lib/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php +++ b/lib/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php @@ -19,7 +19,7 @@ class ServiceUnavailableHttpException extends HttpException /** * @param int|string|null $retryAfter The number of seconds or HTTP-date after which the request may be retried */ - public function __construct(int|string $retryAfter = null, string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(int|string|null $retryAfter = null, string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { if ($retryAfter) { $headers['Retry-After'] = $retryAfter; diff --git a/lib/symfony/http-kernel/Exception/TooManyRequestsHttpException.php b/lib/symfony/http-kernel/Exception/TooManyRequestsHttpException.php index b71fb2508..2f749aa26 100644 --- a/lib/symfony/http-kernel/Exception/TooManyRequestsHttpException.php +++ b/lib/symfony/http-kernel/Exception/TooManyRequestsHttpException.php @@ -21,7 +21,7 @@ class TooManyRequestsHttpException extends HttpException /** * @param int|string|null $retryAfter The number of seconds or HTTP-date after which the request may be retried */ - public function __construct(int|string $retryAfter = null, string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(int|string|null $retryAfter = null, string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { if ($retryAfter) { $headers['Retry-After'] = $retryAfter; diff --git a/lib/symfony/http-kernel/Exception/UnauthorizedHttpException.php b/lib/symfony/http-kernel/Exception/UnauthorizedHttpException.php index c86686128..de8f314b4 100644 --- a/lib/symfony/http-kernel/Exception/UnauthorizedHttpException.php +++ b/lib/symfony/http-kernel/Exception/UnauthorizedHttpException.php @@ -19,7 +19,7 @@ class UnauthorizedHttpException extends HttpException /** * @param string $challenge WWW-Authenticate challenge string */ - public function __construct(string $challenge, string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $challenge, string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { $headers['WWW-Authenticate'] = $challenge; diff --git a/lib/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php b/lib/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php index d58af6c2b..162aa30d6 100644 --- a/lib/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php +++ b/lib/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class UnprocessableEntityHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(422, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php b/lib/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php index 3060f1f91..736337bab 100644 --- a/lib/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php +++ b/lib/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php @@ -16,7 +16,7 @@ namespace Symfony\Component\HttpKernel\Exception; */ class UnsupportedMediaTypeHttpException extends HttpException { - public function __construct(string $message = '', \Throwable $previous = null, int $code = 0, array $headers = []) + public function __construct(string $message = '', ?\Throwable $previous = null, int $code = 0, array $headers = []) { parent::__construct(415, $message, $previous, $headers, $code); } diff --git a/lib/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php index 55305d44e..7eea1aed4 100644 --- a/lib/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php +++ b/lib/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php @@ -34,7 +34,7 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere * * @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported */ - public function __construct(?SurrogateInterface $surrogate, FragmentRendererInterface $inlineStrategy, UriSigner $signer = null) + public function __construct(?SurrogateInterface $surrogate, FragmentRendererInterface $inlineStrategy, ?UriSigner $signer = null) { $this->surrogate = $surrogate; $this->inlineStrategy = $inlineStrategy; diff --git a/lib/symfony/http-kernel/Fragment/FragmentUriGenerator.php b/lib/symfony/http-kernel/Fragment/FragmentUriGenerator.php index aeef41546..59423293e 100644 --- a/lib/symfony/http-kernel/Fragment/FragmentUriGenerator.php +++ b/lib/symfony/http-kernel/Fragment/FragmentUriGenerator.php @@ -28,14 +28,14 @@ final class FragmentUriGenerator implements FragmentUriGeneratorInterface private ?UriSigner $signer; private ?RequestStack $requestStack; - public function __construct(string $fragmentPath, UriSigner $signer = null, RequestStack $requestStack = null) + public function __construct(string $fragmentPath, ?UriSigner $signer = null, ?RequestStack $requestStack = null) { $this->fragmentPath = $fragmentPath; $this->signer = $signer; $this->requestStack = $requestStack; } - public function generate(ControllerReference $controller, Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string + public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string { if (null === $request && (null === $this->requestStack || null === $request = $this->requestStack->getCurrentRequest())) { throw new \LogicException('Generating a fragment URL can only be done when handling a Request.'); diff --git a/lib/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php b/lib/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php index 968c002b9..6b1317c3a 100644 --- a/lib/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php +++ b/lib/symfony/http-kernel/Fragment/FragmentUriGeneratorInterface.php @@ -28,5 +28,5 @@ interface FragmentUriGeneratorInterface * @param bool $strict Whether to allow non-scalar attributes or not * @param bool $sign Whether to sign the URL or not */ - public function generate(ControllerReference $controller, Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string; + public function generate(ControllerReference $controller, ?Request $request = null, bool $absolute = false, bool $strict = true, bool $sign = true): string; } diff --git a/lib/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php index d5b6c4cd3..edcf9938c 100644 --- a/lib/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php +++ b/lib/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php @@ -32,7 +32,7 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer /** * @param string|null $globalDefaultTemplate The global default content (it can be a template name or the content) */ - public function __construct(Environment $twig = null, UriSigner $signer = null, string $globalDefaultTemplate = null, string $charset = 'utf-8') + public function __construct(?Environment $twig = null, ?UriSigner $signer = null, ?string $globalDefaultTemplate = null, string $charset = 'utf-8') { $this->twig = $twig; $this->globalDefaultTemplate = $globalDefaultTemplate; diff --git a/lib/symfony/http-kernel/Fragment/InlineFragmentRenderer.php b/lib/symfony/http-kernel/Fragment/InlineFragmentRenderer.php index ba3f6be70..1999603a3 100644 --- a/lib/symfony/http-kernel/Fragment/InlineFragmentRenderer.php +++ b/lib/symfony/http-kernel/Fragment/InlineFragmentRenderer.php @@ -30,7 +30,7 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer private HttpKernelInterface $kernel; private ?EventDispatcherInterface $dispatcher; - public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null) + public function __construct(HttpKernelInterface $kernel, ?EventDispatcherInterface $dispatcher = null) { $this->kernel = $kernel; $this->dispatcher = $dispatcher; diff --git a/lib/symfony/polyfill-php80/Resources/stubs/ValueError.php b/lib/symfony/http-kernel/HttpCache/CacheWasLockedException.php similarity index 66% rename from lib/symfony/polyfill-php80/Resources/stubs/ValueError.php rename to lib/symfony/http-kernel/HttpCache/CacheWasLockedException.php index 783dbc28c..f13946ad7 100644 --- a/lib/symfony/polyfill-php80/Resources/stubs/ValueError.php +++ b/lib/symfony/http-kernel/HttpCache/CacheWasLockedException.php @@ -9,8 +9,11 @@ * file that was distributed with this source code. */ -if (\PHP_VERSION_ID < 80000) { - class ValueError extends Error - { - } +namespace Symfony\Component\HttpKernel\HttpCache; + +/** + * @internal + */ +class CacheWasLockedException extends \Exception +{ } diff --git a/lib/symfony/http-kernel/HttpCache/Esi.php b/lib/symfony/http-kernel/HttpCache/Esi.php index 5db840a80..e8faf0fdb 100644 --- a/lib/symfony/http-kernel/HttpCache/Esi.php +++ b/lib/symfony/http-kernel/HttpCache/Esi.php @@ -42,7 +42,7 @@ class Esi extends AbstractSurrogate } } - public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = ''): string + public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = ''): string { $html = sprintf('', $uri, diff --git a/lib/symfony/http-kernel/HttpCache/HttpCache.php b/lib/symfony/http-kernel/HttpCache/HttpCache.php index eabacfec6..bce0e99b5 100644 --- a/lib/symfony/http-kernel/HttpCache/HttpCache.php +++ b/lib/symfony/http-kernel/HttpCache/HttpCache.php @@ -17,6 +17,7 @@ namespace Symfony\Component\HttpKernel\HttpCache; +use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\HttpKernelInterface; @@ -89,7 +90,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface * Unless your application needs to process events on cache hits, it is recommended * to set this to false to avoid having to bootstrap the Symfony framework on a cache hit. */ - public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = []) + public function __construct(HttpKernelInterface $kernel, StoreInterface $store, ?SurrogateInterface $surrogate = null, array $options = []) { $this->store = $store; $this->kernel = $kernel; @@ -218,7 +219,13 @@ class HttpCache implements HttpKernelInterface, TerminableInterface $this->record($request, 'reload'); $response = $this->fetch($request, $catch); } else { - $response = $this->lookup($request, $catch); + $response = null; + do { + try { + $response = $this->lookup($request, $catch); + } catch (CacheWasLockedException) { + } + } while (null === $response); } $this->restoreResponseBody($request, $response); @@ -237,7 +244,9 @@ class HttpCache implements HttpKernelInterface, TerminableInterface $response->prepare($request); - $response->isNotModified($request); + if (HttpKernelInterface::MAIN_REQUEST === $type) { + $response->isNotModified($request); + } return $response; } @@ -465,7 +474,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface * * @return Response */ - protected function forward(Request $request, bool $catch = false, Response $entry = null) + protected function forward(Request $request, bool $catch = false, ?Response $entry = null) { $this->surrogate?->addSurrogateCapability($request); @@ -573,15 +582,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface // wait for the lock to be released if ($this->waitForLock($request)) { - // replace the current entry with the fresh one - $new = $this->lookup($request); - $entry->headers = $new->headers; - $entry->setContent($new->getContent()); - $entry->setStatusCode($new->getStatusCode()); - $entry->setProtocolVersion($new->getProtocolVersion()); - foreach ($new->headers->getCookies() as $cookie) { - $entry->headers->setCookie($cookie); - } + throw new CacheWasLockedException(); // unwind back to handle(), try again } else { // backend is slow as hell, send a 503 response (to avoid the dog pile effect) $entry->setStatusCode(503); @@ -723,7 +724,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface $path .= '?'.$qs; } - return $request->getMethod().' '.$path; + try { + return $request->getMethod().' '.$path; + } catch (SuspiciousOperationException $e) { + return '_BAD_METHOD_ '.$path; + } } /** diff --git a/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php b/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php index 57b5d2196..bf7ec78f2 100644 --- a/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php +++ b/lib/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php @@ -51,7 +51,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface private array $ageDirectives = [ 'max-age' => null, 's-maxage' => null, - 'expires' => null, + 'expires' => false, ]; /** @@ -82,15 +82,30 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface return; } - $isHeuristicallyCacheable = $response->headers->hasCacheControlDirective('public'); $maxAge = $response->headers->hasCacheControlDirective('max-age') ? (int) $response->headers->getCacheControlDirective('max-age') : null; - $this->storeRelativeAgeDirective('max-age', $maxAge, $age, $isHeuristicallyCacheable); $sharedMaxAge = $response->headers->hasCacheControlDirective('s-maxage') ? (int) $response->headers->getCacheControlDirective('s-maxage') : $maxAge; - $this->storeRelativeAgeDirective('s-maxage', $sharedMaxAge, $age, $isHeuristicallyCacheable); - $expires = $response->getExpires(); $expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null; - $this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0, $isHeuristicallyCacheable); + + // See https://datatracker.ietf.org/doc/html/rfc7234#section-4.2.2 + // If a response is "public" but does not have maximum lifetime, heuristics might be applied. + // Do not store NULL values so the final response can have more limiting value from other responses. + $isHeuristicallyCacheable = $response->headers->hasCacheControlDirective('public') + && null === $maxAge + && null === $sharedMaxAge + && null === $expires; + + if (!$isHeuristicallyCacheable || null !== $maxAge || null !== $expires) { + $this->storeRelativeAgeDirective('max-age', $maxAge, $expires, $age); + } + + if (!$isHeuristicallyCacheable || null !== $sharedMaxAge || null !== $expires) { + $this->storeRelativeAgeDirective('s-maxage', $sharedMaxAge, $expires, $age); + } + + if (null !== $expires) { + $this->ageDirectives['expires'] = true; + } if (false !== $this->lastModified) { $lastModified = $response->getLastModified(); @@ -152,9 +167,9 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface } } - if (is_numeric($this->ageDirectives['expires'])) { + if ($this->ageDirectives['expires'] && null !== $maxAge) { $date = clone $response->getDate(); - $date = $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds'); + $date = $date->modify('+'.$maxAge.' seconds'); $response->setExpires($date); } } @@ -204,33 +219,16 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface * we have to subtract the age so that the value is normalized for an age of 0. * * If the value is lower than the currently stored value, we update the value, to keep a rolling - * minimal value of each instruction. - * - * If the value is NULL and the isHeuristicallyCacheable parameter is false, the directive will - * not be set on the final response. In this case, not all responses had the directive set and no - * value can be found that satisfies the requirements of all responses. The directive will be dropped - * from the final response. - * - * If the isHeuristicallyCacheable parameter is true, however, the current response has been marked - * as cacheable in a public (shared) cache, but did not provide an explicit lifetime that would serve - * as an upper bound. In this case, we can proceed and possibly keep the directive on the final response. + * minimal value of each instruction. If the value is NULL, the directive will not be set on the final response. */ - private function storeRelativeAgeDirective(string $directive, ?int $value, int $age, bool $isHeuristicallyCacheable): void + private function storeRelativeAgeDirective(string $directive, ?int $value, ?int $expires, int $age): void { - if (null === $value) { - if ($isHeuristicallyCacheable) { - /* - * See https://datatracker.ietf.org/doc/html/rfc7234#section-4.2.2 - * This particular response does not require maximum lifetime; heuristics might be applied. - * Other responses, however, might have more stringent requirements on maximum lifetime. - * So, return early here so that the final response can have the more limiting value set. - */ - return; - } + if (null === $value && null === $expires) { $this->ageDirectives[$directive] = false; } if (false !== $this->ageDirectives[$directive]) { + $value = min($value ?? PHP_INT_MAX, $expires ?? PHP_INT_MAX); $value -= $age; $this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value; } diff --git a/lib/symfony/http-kernel/HttpCache/Ssi.php b/lib/symfony/http-kernel/HttpCache/Ssi.php index b17c90ac6..8cf4e4907 100644 --- a/lib/symfony/http-kernel/HttpCache/Ssi.php +++ b/lib/symfony/http-kernel/HttpCache/Ssi.php @@ -36,7 +36,7 @@ class Ssi extends AbstractSurrogate } } - public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = ''): string + public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = ''): string { return sprintf('', $uri); } diff --git a/lib/symfony/http-kernel/HttpCache/Store.php b/lib/symfony/http-kernel/HttpCache/Store.php index 3f21e383f..7f7f1a1a1 100644 --- a/lib/symfony/http-kernel/HttpCache/Store.php +++ b/lib/symfony/http-kernel/HttpCache/Store.php @@ -474,7 +474,7 @@ class Store implements StoreInterface /** * Restores a Response from the HTTP headers and body. */ - private function restoreResponse(array $headers, string $path = null): ?Response + private function restoreResponse(array $headers, ?string $path = null): ?Response { $status = $headers['X-Status'][0]; unset($headers['X-Status']); diff --git a/lib/symfony/http-kernel/HttpCache/SurrogateInterface.php b/lib/symfony/http-kernel/HttpCache/SurrogateInterface.php index e444458f7..5ff10c963 100644 --- a/lib/symfony/http-kernel/HttpCache/SurrogateInterface.php +++ b/lib/symfony/http-kernel/HttpCache/SurrogateInterface.php @@ -58,7 +58,7 @@ interface SurrogateInterface * @param string|null $alt An alternate URI * @param string $comment A comment to add as an esi:include tag */ - public function renderIncludeTag(string $uri, string $alt = null, bool $ignoreErrors = true, string $comment = ''): string; + public function renderIncludeTag(string $uri, ?string $alt = null, bool $ignoreErrors = true, string $comment = ''): string; /** * Replaces a Response Surrogate tags with the included resource content. diff --git a/lib/symfony/http-kernel/HttpClientKernel.php b/lib/symfony/http-kernel/HttpClientKernel.php index 1d8c30278..7c719e8e6 100644 --- a/lib/symfony/http-kernel/HttpClientKernel.php +++ b/lib/symfony/http-kernel/HttpClientKernel.php @@ -33,7 +33,7 @@ final class HttpClientKernel implements HttpKernelInterface { private HttpClientInterface $client; - public function __construct(HttpClientInterface $client = null) + public function __construct(?HttpClientInterface $client = null) { if (null === $client && !class_exists(HttpClient::class)) { throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); diff --git a/lib/symfony/http-kernel/HttpKernel.php b/lib/symfony/http-kernel/HttpKernel.php index d2cf4eaee..6460bebbd 100644 --- a/lib/symfony/http-kernel/HttpKernel.php +++ b/lib/symfony/http-kernel/HttpKernel.php @@ -57,7 +57,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface private ArgumentResolverInterface $argumentResolver; private bool $handleAllThrowables; - public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverInterface $argumentResolver = null, bool $handleAllThrowables = false) + public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, ?RequestStack $requestStack = null, ?ArgumentResolverInterface $argumentResolver = null, bool $handleAllThrowables = false) { $this->dispatcher = $dispatcher; $this->resolver = $resolver; @@ -118,7 +118,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface /** * @internal */ - public function terminateWithException(\Throwable $exception, Request $request = null): void + public function terminateWithException(\Throwable $exception, ?Request $request = null): void { if (!$request ??= $this->requestStack->getMainRequest()) { throw $exception; diff --git a/lib/symfony/http-kernel/HttpKernelBrowser.php b/lib/symfony/http-kernel/HttpKernelBrowser.php index 0f3630e7f..169789dda 100644 --- a/lib/symfony/http-kernel/HttpKernelBrowser.php +++ b/lib/symfony/http-kernel/HttpKernelBrowser.php @@ -36,7 +36,7 @@ class HttpKernelBrowser extends AbstractBrowser /** * @param array $server The server parameters (equivalent of $_SERVER) */ - public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) + public function __construct(HttpKernelInterface $kernel, array $server = [], ?History $history = null, ?CookieJar $cookieJar = null) { // These class properties must be set before calling the parent constructor, as it may depend on it. $this->kernel = $kernel; diff --git a/lib/symfony/http-kernel/Kernel.php b/lib/symfony/http-kernel/Kernel.php index 6247db901..04f788167 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.2'; - public const VERSION_ID = 60402; + public const VERSION = '6.4.23'; + public const VERSION_ID = 60423; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 2; + public const RELEASE_VERSION = 23; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2026'; @@ -407,7 +407,8 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl $cachePath = $cache->getPath(); // Silence E_WARNING to ignore "include" failures - don't use "@" to prevent silencing fatal errors - $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); + $errorLevel = error_reporting(); + error_reporting($errorLevel & ~\E_WARNING); try { if (is_file($cachePath) && \is_object($this->container = include $cachePath) @@ -539,10 +540,18 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl touch($oldContainerDir.'.legacy'); } - $preload = $this instanceof WarmableInterface ? (array) $this->warmUp($this->container->getParameter('kernel.cache_dir'), $buildDir) : []; + $buildDir = $this->container->getParameter('kernel.build_dir'); + $cacheDir = $this->container->getParameter('kernel.cache_dir'); + $preload = $this instanceof WarmableInterface ? (array) $this->warmUp($cacheDir, $buildDir) : []; if ($this->container->has('cache_warmer')) { - $preload = array_merge($preload, (array) $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'), $buildDir)); + $cacheWarmer = $this->container->get('cache_warmer'); + + if ($cacheDir !== $buildDir) { + $cacheWarmer->enableOptionalWarmers(); + } + + $preload = array_merge($preload, (array) $cacheWarmer->warmUp($cacheDir, $buildDir)); } if ($preload && file_exists($preloadFile = $buildDir.'/'.$class.'.preload.php')) { diff --git a/lib/symfony/http-kernel/Log/DebugLoggerConfigurator.php b/lib/symfony/http-kernel/Log/DebugLoggerConfigurator.php index 537c10040..e036f398e 100644 --- a/lib/symfony/http-kernel/Log/DebugLoggerConfigurator.php +++ b/lib/symfony/http-kernel/Log/DebugLoggerConfigurator.php @@ -20,7 +20,7 @@ class DebugLoggerConfigurator { private ?object $processor = null; - public function __construct(callable $processor, bool $enable = null) + public function __construct(callable $processor, ?bool $enable = null) { if ($enable ?? !\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { $this->processor = \is_object($processor) ? $processor : $processor(...); diff --git a/lib/symfony/http-kernel/Log/DebugLoggerInterface.php b/lib/symfony/http-kernel/Log/DebugLoggerInterface.php index 1940c80a9..956abc6f3 100644 --- a/lib/symfony/http-kernel/Log/DebugLoggerInterface.php +++ b/lib/symfony/http-kernel/Log/DebugLoggerInterface.php @@ -33,14 +33,14 @@ interface DebugLoggerInterface * timestamp_rfc3339: string, * }> */ - public function getLogs(Request $request = null); + public function getLogs(?Request $request = null); /** * Returns the number of errors. * * @return int */ - public function countErrors(Request $request = null); + public function countErrors(?Request $request = null); /** * Removes all log records. diff --git a/lib/symfony/http-kernel/Log/Logger.php b/lib/symfony/http-kernel/Log/Logger.php index 11d35b7e2..50578a25e 100644 --- a/lib/symfony/http-kernel/Log/Logger.php +++ b/lib/symfony/http-kernel/Log/Logger.php @@ -57,7 +57,7 @@ class Logger extends AbstractLogger implements DebugLoggerInterface /** * @param string|resource|null $output */ - public function __construct(string $minLevel = null, $output = null, callable $formatter = null, private readonly ?RequestStack $requestStack = null, bool $debug = false) + public function __construct(?string $minLevel = null, $output = null, ?callable $formatter = null, private readonly ?RequestStack $requestStack = null, bool $debug = false) { if (null === $minLevel) { $minLevel = null === $output || 'php://stdout' === $output || 'php://stderr' === $output ? LogLevel::ERROR : LogLevel::WARNING; @@ -79,7 +79,7 @@ class Logger extends AbstractLogger implements DebugLoggerInterface $this->minLevelIndex = self::LEVELS[$minLevel]; $this->formatter = null !== $formatter ? $formatter(...) : $this->format(...); - if ($output && false === $this->handle = \is_resource($output) ? $output : @fopen($output, 'a')) { + if ($output && false === $this->handle = \is_string($output) ? @fopen($output, 'a') : $output) { throw new InvalidArgumentException(sprintf('Unable to open "%s".', $output)); } $this->debug = $debug; @@ -112,7 +112,7 @@ class Logger extends AbstractLogger implements DebugLoggerInterface } } - public function getLogs(Request $request = null): array + public function getLogs(?Request $request = null): array { if ($request) { return $this->logs[spl_object_id($request)] ?? []; @@ -121,7 +121,7 @@ class Logger extends AbstractLogger implements DebugLoggerInterface return array_merge(...array_values($this->logs)); } - public function countErrors(Request $request = null): int + public function countErrors(?Request $request = null): int { if ($request) { return $this->errorCount[spl_object_id($request)] ?? 0; diff --git a/lib/symfony/http-kernel/Profiler/FileProfilerStorage.php b/lib/symfony/http-kernel/Profiler/FileProfilerStorage.php index df61f716f..d2372c30e 100644 --- a/lib/symfony/http-kernel/Profiler/FileProfilerStorage.php +++ b/lib/symfony/http-kernel/Profiler/FileProfilerStorage.php @@ -45,7 +45,7 @@ class FileProfilerStorage implements ProfilerStorageInterface /** * @param \Closure|null $filter A filter to apply on the list of tokens */ - public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null, string $statusCode = null/* , \Closure $filter = null */): array + public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?int $start = null, ?int $end = null, ?string $statusCode = null/* , \Closure $filter = null */): array { $filter = 7 < \func_num_args() ? func_get_arg(7) : null; $file = $this->getIndexFilename(); @@ -59,7 +59,7 @@ class FileProfilerStorage implements ProfilerStorageInterface $result = []; while (\count($result) < $limit && $line = $this->readLineFromFile($file)) { - $values = str_getcsv($line); + $values = str_getcsv($line, ',', '"', '\\'); if (7 > \count($values)) { // skip invalid lines @@ -193,7 +193,7 @@ class FileProfilerStorage implements ProfilerStorageInterface $profile->getParentToken(), $profile->getStatusCode(), $profile->getVirtualType() ?? 'request', - ]); + ], ',', '"', '\\'); fclose($file); if (1 === mt_rand(1, 10)) { @@ -272,7 +272,7 @@ class FileProfilerStorage implements ProfilerStorageInterface /** * @return Profile */ - protected function createProfileFromData(string $token, array $data, Profile $parent = null) + protected function createProfileFromData(string $token, array $data, ?Profile $parent = null) { $profile = new Profile($token); $profile->setIp($data['ip']); @@ -300,7 +300,7 @@ class FileProfilerStorage implements ProfilerStorageInterface return $profile; } - private function doRead($token, Profile $profile = null): ?Profile + private function doRead($token, ?Profile $profile = null): ?Profile { if (!$token || !file_exists($file = $this->getFilename($token))) { return null; @@ -334,7 +334,7 @@ class FileProfilerStorage implements ProfilerStorageInterface } while ($line = fgets($handle)) { - $values = str_getcsv($line); + $values = str_getcsv($line, ',', '"', '\\'); if (7 > \count($values)) { // skip invalid lines diff --git a/lib/symfony/http-kernel/Profiler/Profiler.php b/lib/symfony/http-kernel/Profiler/Profiler.php index 04ab0670d..fd5b28531 100644 --- a/lib/symfony/http-kernel/Profiler/Profiler.php +++ b/lib/symfony/http-kernel/Profiler/Profiler.php @@ -37,7 +37,7 @@ class Profiler implements ResetInterface private bool $initiallyEnabled = true; private bool $enabled = true; - public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, bool $enable = true) + public function __construct(ProfilerStorageInterface $storage, ?LoggerInterface $logger = null, bool $enable = true) { $this->storage = $storage; $this->logger = $logger; @@ -128,7 +128,7 @@ class Profiler implements ResetInterface * * @see https://php.net/datetime.formats for the supported date/time formats */ - public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?string $start, ?string $end, string $statusCode = null/* , \Closure $filter = null */): array + public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?string $start, ?string $end, ?string $statusCode = null/* , \Closure $filter = null */): array { $filter = 7 < \func_num_args() ? func_get_arg(7) : null; @@ -138,7 +138,7 @@ class Profiler implements ResetInterface /** * Collects data for the given Response. */ - public function collect(Request $request, Response $response, \Throwable $exception = null): ?Profile + public function collect(Request $request, Response $response, ?\Throwable $exception = null): ?Profile { if (false === $this->enabled) { return null; diff --git a/lib/symfony/http-kernel/Profiler/ProfilerStorageInterface.php b/lib/symfony/http-kernel/Profiler/ProfilerStorageInterface.php index 14b8993b6..e2a25bc99 100644 --- a/lib/symfony/http-kernel/Profiler/ProfilerStorageInterface.php +++ b/lib/symfony/http-kernel/Profiler/ProfilerStorageInterface.php @@ -35,7 +35,7 @@ interface ProfilerStorageInterface * @param string|null $statusCode The response status code * @param \Closure|null $filter A filter to apply on the list of tokens */ - public function find(?string $ip, ?string $url, ?int $limit, ?string $method, int $start = null, int $end = null/* , string $statusCode = null, \Closure $filter = null */): array; + public function find(?string $ip, ?string $url, ?int $limit, ?string $method, ?int $start = null, ?int $end = null/* , string $statusCode = null, \Closure $filter = null */): array; /** * Reads data associated with the given token. diff --git a/lib/symfony/http-kernel/Resources/welcome.html.php b/lib/symfony/http-kernel/Resources/welcome.html.php index d36b97527..03453c5c7 100644 --- a/lib/symfony/http-kernel/Resources/welcome.html.php +++ b/lib/symfony/http-kernel/Resources/welcome.html.php @@ -1,10 +1,10 @@ - - + + Welcome to Symfony! - +