diff --git a/composer.json b/composer.json index c4e22c199..b582b6e8e 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "project", "license": "AGPL-3.0-only", "require": { - "php": ">=8.1.0 <8.5.0", + "php": ">=8.2.0 <8.5.0", "ext-ctype": "*", "ext-dom": "*", "ext-gd": "*", @@ -15,18 +15,21 @@ "apereo/phpcas": "dev-master", "guzzlehttp/guzzle": "^7.5.1", "league/oauth2-google": "^4.0.1", - "nikic/php-parser": "^4.14.0", + "nikic/php-parser": "dev-master", "pear/archive_tar": "~1.4.14", "pelago/emogrifier": "^7.2.0", "psr/log": "^3.0.0", "scssphp/scssphp": "dev-combodo/1.x", "symfony/console": "~6.4.0", "symfony/dotenv": "~6.4.0", + "symfony/form": "^6.4", "symfony/framework-bundle": "~6.4.0", "symfony/http-foundation": "~6.4.0", "symfony/http-kernel": "~6.4.0", "symfony/runtime": "~6.4.0", + "symfony/security-csrf": "~6.4.0", "symfony/twig-bundle": "~6.4.0", + "symfony/validator" : "~6.4.0", "symfony/var-dumper": "~6.4.0", "symfony/yaml": "~6.4.0", "symfony/mailer": "~6.4.0", @@ -40,6 +43,10 @@ "symfony/web-profiler-bundle": "~6.4.0" }, "repositories": [ + { + "type": "vcs", + "url": "https://github.com/Combodo/PHP-Parser" + }, { "type": "vcs", "url": "https://github.com/EsupPortail/phpCAS" @@ -60,7 +67,7 @@ }, "config": { "platform": { - "php": "8.1.0" + "php": "8.2.0" }, "vendor-dir": "lib", "preferred-install": { @@ -80,7 +87,6 @@ "sources" ], "exclude-from-classmap": [ - "application/twigextension.class.inc.php", "core/oql/build/PHP/", "core/apc-emulation.php", "application/startup.inc.php", @@ -100,7 +106,7 @@ "extra": { "symfony": { "allow-contrib": false, - "require": "3.4.*" + "require": "6.4.*" }, "runtime": { "dotenv_path": "resources/symfony/.env" diff --git a/composer.lock b/composer.lock index 6a95f3e03..ca84500c7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "eebbdc6c10a479b0e62fc18d88496f5c", + "content-hash": "1cca58a0e26794fb9c546a001f7f7de8", "packages": [ { "name": "apereo/phpcas", @@ -236,16 +236,16 @@ }, { "name": "firebase/php-jwt", - "version": "v7.0.2", + "version": "v7.0.5", "source": { "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "5645b43af647b6947daac1d0f659dd1fbe8d3b65" + "url": "https://github.com/googleapis/php-jwt.git", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5645b43af647b6947daac1d0f659dd1fbe8d3b65", - "reference": "5645b43af647b6947daac1d0f659dd1fbe8d3b65", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", "shasum": "" }, "require": { @@ -253,6 +253,7 @@ }, "require-dev": { "guzzlehttp/guzzle": "^7.4", + "phpfastcache/phpfastcache": "^9.2", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", @@ -292,10 +293,10 @@ "php" ], "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v7.0.2" + "issues": "https://github.com/googleapis/php-jwt/issues", + "source": "https://github.com/googleapis/php-jwt/tree/v7.0.5" }, - "time": "2025-12-16T22:17:28+00:00" + "time": "2026-04-01T20:38:03+00:00" }, { "name": "guzzlehttp/guzzle", @@ -508,16 +509,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.8.0", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884", + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884", "shasum": "" }, "require": { @@ -533,6 +534,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", + "jshttp/mime-db": "1.54.0.1", "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { @@ -604,7 +606,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.8.0" + "source": "https://github.com/guzzle/psr7/tree/2.9.0" }, "funding": [ { @@ -620,7 +622,7 @@ "type": "tidelift" } ], - "time": "2025-08-23T21:21:41+00:00" + "time": "2026-03-10T16:41:02+00:00" }, { "name": "league/oauth2-client", @@ -689,20 +691,20 @@ }, { "name": "league/oauth2-google", - "version": "4.1.0", + "version": "4.2.0", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-google.git", - "reference": "8b9bb43740ac6d994aca881a35f7bacbe98c0ffb" + "reference": "72be69505f890ea8b6d4e716f619b3c10a1f5010" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-google/zipball/8b9bb43740ac6d994aca881a35f7bacbe98c0ffb", - "reference": "8b9bb43740ac6d994aca881a35f7bacbe98c0ffb", + "url": "https://api.github.com/repos/thephpleague/oauth2-google/zipball/72be69505f890ea8b6d4e716f619b3c10a1f5010", + "reference": "72be69505f890ea8b6d4e716f619b3c10a1f5010", "shasum": "" }, "require": { - "league/oauth2-client": "^2.0", + "league/oauth2-client": "^2.0 || ^3.0", "php": "^7.3 || ^8.0" }, "require-dev": { @@ -738,42 +740,54 @@ ], "support": { "issues": "https://github.com/thephpleague/oauth2-google/issues", - "source": "https://github.com/thephpleague/oauth2-google/tree/4.1.0" + "source": "https://github.com/thephpleague/oauth2-google/tree/4.2.0" }, - "time": "2025-12-15T12:24:14+00:00" + "time": "2026-03-09T09:36:58+00:00" }, { "name": "nikic/php-parser", - "version": "v4.19.5", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837" + "url": "https://github.com/Combodo/PHP-Parser.git", + "reference": "b27e577f70d2114b8ba96105e403017919a8611b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", - "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", + "url": "https://api.github.com/repos/Combodo/PHP-Parser/zipball/b27e577f70d2114b8ba96105e403017919a8611b", + "reference": "b27e577f70d2114b8ba96105e403017919a8611b", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.1" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, + "default-branch": true, "bin": [ "bin/php-parse" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" } }, - "notification-url": "https://packagist.org/downloads/", + "autoload-dev": { + "psr-4": { + "PhpParser\\": "test/PhpParser/" + } + }, "license": [ "BSD-3-Clause" ], @@ -788,10 +802,9 @@ "php" ], "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.5" + "source": "https://github.com/Combodo/PHP-Parser/tree/master" }, - "time": "2025-12-06T11:45:25+00:00" + "time": "2026-03-31T15:49:45+00:00" }, { "name": "pear/archive_tar", @@ -1726,16 +1739,16 @@ }, { "name": "symfony/cache", - "version": "v6.4.33", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "5b088fa41eb9568748dc255c45e4054c387ba73b" + "reference": "5b94fba945d1f9e7929cffd50e7a17f1ac36f10b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/5b088fa41eb9568748dc255c45e4054c387ba73b", - "reference": "5b088fa41eb9568748dc255c45e4054c387ba73b", + "url": "https://api.github.com/repos/symfony/cache/zipball/5b94fba945d1f9e7929cffd50e7a17f1ac36f10b", + "reference": "5b94fba945d1f9e7929cffd50e7a17f1ac36f10b", "shasum": "" }, "require": { @@ -1802,7 +1815,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.33" + "source": "https://github.com/symfony/cache/tree/v6.4.36" }, "funding": [ { @@ -1822,7 +1835,7 @@ "type": "tidelift" } ], - "time": "2026-01-27T15:05:20+00:00" + "time": "2026-03-30T14:52:43+00:00" }, { "name": "symfony/cache-contracts", @@ -1902,16 +1915,16 @@ }, { "name": "symfony/config", - "version": "v6.4.32", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "d445badf0ad2c2a492e38c0378c39997a56ef97b" + "reference": "ce9cb0c0d281aaf188b802d4968e42bfb60701e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/d445badf0ad2c2a492e38c0378c39997a56ef97b", - "reference": "d445badf0ad2c2a492e38c0378c39997a56ef97b", + "url": "https://api.github.com/repos/symfony/config/zipball/ce9cb0c0d281aaf188b802d4968e42bfb60701e9", + "reference": "ce9cb0c0d281aaf188b802d4968e42bfb60701e9", "shasum": "" }, "require": { @@ -1957,7 +1970,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.32" + "source": "https://github.com/symfony/config/tree/v6.4.34" }, "funding": [ { @@ -1977,20 +1990,20 @@ "type": "tidelift" } ], - "time": "2026-01-13T08:40:30+00:00" + "time": "2026-02-24T17:34:50+00:00" }, { "name": "symfony/console", - "version": "v6.4.32", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3" + "reference": "9f481cfb580db8bcecc9b2d4c63f3e13df022ad5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3", - "reference": "0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3", + "url": "https://api.github.com/repos/symfony/console/zipball/9f481cfb580db8bcecc9b2d4c63f3e13df022ad5", + "reference": "9f481cfb580db8bcecc9b2d4c63f3e13df022ad5", "shasum": "" }, "require": { @@ -2055,7 +2068,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.32" + "source": "https://github.com/symfony/console/tree/v6.4.36" }, "funding": [ { @@ -2075,20 +2088,20 @@ "type": "tidelift" } ], - "time": "2026-01-13T08:45:59+00:00" + "time": "2026-03-27T15:30:51+00:00" }, { "name": "symfony/css-selector", - "version": "v6.4.24", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "9b784413143701aa3c94ac1869a159a9e53e8761" + "reference": "b0314c186f1464de048cce58979ff1625ca88bbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/9b784413143701aa3c94ac1869a159a9e53e8761", - "reference": "9b784413143701aa3c94ac1869a159a9e53e8761", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/b0314c186f1464de048cce58979ff1625ca88bbb", + "reference": "b0314c186f1464de048cce58979ff1625ca88bbb", "shasum": "" }, "require": { @@ -2124,7 +2137,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.24" + "source": "https://github.com/symfony/css-selector/tree/v6.4.34" }, "funding": [ { @@ -2144,20 +2157,20 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2026-02-16T08:37:21+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.32", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "b17882e933c4c606620247b6708ab53aa3b88753" + "reference": "cd7881a6dc84b780411199cd0584e1a53a3b9ba7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b17882e933c4c606620247b6708ab53aa3b88753", - "reference": "b17882e933c4c606620247b6708ab53aa3b88753", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/cd7881a6dc84b780411199cd0584e1a53a3b9ba7", + "reference": "cd7881a6dc84b780411199cd0584e1a53a3b9ba7", "shasum": "" }, "require": { @@ -2209,7 +2222,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.32" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.36" }, "funding": [ { @@ -2229,7 +2242,7 @@ "type": "tidelift" } ], - "time": "2026-01-23T10:54:33+00:00" + "time": "2026-03-30T16:39:36+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2300,16 +2313,16 @@ }, { "name": "symfony/dotenv", - "version": "v6.4.30", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "924edbc9631b75302def0258ed1697948b17baf6" + "reference": "cae019cc92a46fe9e498ea011107f26bdf5d897f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/924edbc9631b75302def0258ed1697948b17baf6", - "reference": "924edbc9631b75302def0258ed1697948b17baf6", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/cae019cc92a46fe9e498ea011107f26bdf5d897f", + "reference": "cae019cc92a46fe9e498ea011107f26bdf5d897f", "shasum": "" }, "require": { @@ -2354,7 +2367,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.30" + "source": "https://github.com/symfony/dotenv/tree/v6.4.36" }, "funding": [ { @@ -2374,20 +2387,20 @@ "type": "tidelift" } ], - "time": "2025-11-14T17:33:48+00:00" + "time": "2026-03-30T07:25:04+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.32", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8c18400784fcb014dc73c8d5601a9576af7f8ad4" + "reference": "2ea68f0e1835ad6a126f93bbc14cd236c10ab361" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8c18400784fcb014dc73c8d5601a9576af7f8ad4", - "reference": "8c18400784fcb014dc73c8d5601a9576af7f8ad4", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/2ea68f0e1835ad6a126f93bbc14cd236c10ab361", + "reference": "2ea68f0e1835ad6a126f93bbc14cd236c10ab361", "shasum": "" }, "require": { @@ -2433,7 +2446,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.32" + "source": "https://github.com/symfony/error-handler/tree/v6.4.36" }, "funding": [ { @@ -2453,20 +2466,20 @@ "type": "tidelift" } ], - "time": "2026-01-19T19:28:19+00:00" + "time": "2026-03-10T15:56:14+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.32", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "99d7e101826e6610606b9433248f80c1997cd20b" + "reference": "fc828863e26ceec86e2513b5e46aa0b149d76b69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99d7e101826e6610606b9433248f80c1997cd20b", - "reference": "99d7e101826e6610606b9433248f80c1997cd20b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fc828863e26ceec86e2513b5e46aa0b149d76b69", + "reference": "fc828863e26ceec86e2513b5e46aa0b149d76b69", "shasum": "" }, "require": { @@ -2517,7 +2530,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.32" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.36" }, "funding": [ { @@ -2537,7 +2550,7 @@ "type": "tidelift" } ], - "time": "2026-01-05T11:13:48+00:00" + "time": "2026-03-30T11:18:01+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -2617,16 +2630,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "441c6b69f7222aadae7cbf5df588496d5ee37789" + "reference": "01ffe0411b842f93c571e5c391f289c3fdd498c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/441c6b69f7222aadae7cbf5df588496d5ee37789", - "reference": "441c6b69f7222aadae7cbf5df588496d5ee37789", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/01ffe0411b842f93c571e5c391f289c3fdd498c3", + "reference": "01ffe0411b842f93c571e5c391f289c3fdd498c3", "shasum": "" }, "require": { @@ -2663,7 +2676,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.30" + "source": "https://github.com/symfony/filesystem/tree/v6.4.34" }, "funding": [ { @@ -2683,20 +2696,20 @@ "type": "tidelift" } ], - "time": "2025-11-26T14:43:45+00:00" + "time": "2026-02-24T17:51:06+00:00" }, { "name": "symfony/finder", - "version": "v6.4.33", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "24965ca011dac87431729640feef8bcf7b5523e0" + "reference": "9590e86be1d1c57bfbb16d0dd040345378c20896" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/24965ca011dac87431729640feef8bcf7b5523e0", - "reference": "24965ca011dac87431729640feef8bcf7b5523e0", + "url": "https://api.github.com/repos/symfony/finder/zipball/9590e86be1d1c57bfbb16d0dd040345378c20896", + "reference": "9590e86be1d1c57bfbb16d0dd040345378c20896", "shasum": "" }, "require": { @@ -2731,7 +2744,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.33" + "source": "https://github.com/symfony/finder/tree/v6.4.34" }, "funding": [ { @@ -2751,20 +2764,121 @@ "type": "tidelift" } ], - "time": "2026-01-26T13:03:48+00:00" + "time": "2026-01-28T15:16:37+00:00" }, { - "name": "symfony/framework-bundle", - "version": "v6.4.33", + "name": "symfony/form", + "version": "v6.4.36", "source": { "type": "git", - "url": "https://github.com/symfony/framework-bundle.git", - "reference": "9ef2d0b63b9e855ba351e770a603d89699115801" + "url": "https://github.com/symfony/form.git", + "reference": "3a38a81150400f0a486f8963e21a195311b30b27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/9ef2d0b63b9e855ba351e770a603d89699115801", - "reference": "9ef2d0b63b9e855ba351e770a603d89699115801", + "url": "https://api.github.com/repos/symfony/form/zipball/3a38a81150400f0a486f8963e21a195311b30b27", + "reference": "3a38a81150400f0a486f8963e21a195311b30b27", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/options-resolver": "^5.4|^6.0|^7.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/polyfill-mbstring": "~1.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/doctrine-bridge": "<5.4.21|>=6,<6.2.7", + "symfony/error-handler": "<5.4", + "symfony/framework-bundle": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", + "symfony/translation-contracts": "<2.5", + "symfony/twig-bridge": "<6.3" + }, + "require-dev": { + "doctrine/collections": "^1.0|^2.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/html-sanitizer": "^6.1|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/security-core": "^6.2|^7.0", + "symfony/security-csrf": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Form\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows to easily create, process and reuse HTML forms", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/form/tree/v6.4.36" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-13T14:59:02+00:00" + }, + { + "name": "symfony/framework-bundle", + "version": "v6.4.36", + "source": { + "type": "git", + "url": "https://github.com/symfony/framework-bundle.git", + "reference": "147b02cfa45dcc74a290462551f5ee5c7fa8ab17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/147b02cfa45dcc74a290462551f5ee5c7fa8ab17", + "reference": "147b02cfa45dcc74a290462551f5ee5c7fa8ab17", "shasum": "" }, "require": { @@ -2884,7 +2998,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.33" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.36" }, "funding": [ { @@ -2904,20 +3018,20 @@ "type": "tidelift" } ], - "time": "2026-01-26T14:46:41+00:00" + "time": "2026-03-25T17:41:29+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.33", + "version": "v6.4.35", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "f1a490cc9d595ba7ebe684220e625d1e472ad278" + "reference": "cffffd0a2c037117b742b4f8b379a22a2a33f6d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/f1a490cc9d595ba7ebe684220e625d1e472ad278", - "reference": "f1a490cc9d595ba7ebe684220e625d1e472ad278", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cffffd0a2c037117b742b4f8b379a22a2a33f6d2", + "reference": "cffffd0a2c037117b742b4f8b379a22a2a33f6d2", "shasum": "" }, "require": { @@ -2965,7 +3079,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.33" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.35" }, "funding": [ { @@ -2985,20 +3099,20 @@ "type": "tidelift" } ], - "time": "2026-01-27T15:04:55+00:00" + "time": "2026-03-06T11:15:58+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.33", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "73fa5c999d7f741ca544a97d3c791cc97890ae4d" + "reference": "4087ec02119de450e9ebb60806d69c6bb8c6e468" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/73fa5c999d7f741ca544a97d3c791cc97890ae4d", - "reference": "73fa5c999d7f741ca544a97d3c791cc97890ae4d", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/4087ec02119de450e9ebb60806d69c6bb8c6e468", + "reference": "4087ec02119de450e9ebb60806d69c6bb8c6e468", "shasum": "" }, "require": { @@ -3039,7 +3153,7 @@ "symfony/config": "^6.1|^7.0", "symfony/console": "^5.4|^6.0|^7.0", "symfony/css-selector": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4.1|^7.0.1", "symfony/dom-crawler": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/finder": "^5.4|^6.0|^7.0", @@ -3083,7 +3197,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.33" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.36" }, "funding": [ { @@ -3103,20 +3217,20 @@ "type": "tidelift" } ], - "time": "2026-01-28T10:02:13+00:00" + "time": "2026-03-31T20:38:11+00:00" }, { "name": "symfony/mailer", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "8835f93333474780fda1b987cae37e33c3e026ca" + "reference": "01b846f48e53ee4096692a383637a1fa4d577301" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/8835f93333474780fda1b987cae37e33c3e026ca", - "reference": "8835f93333474780fda1b987cae37e33c3e026ca", + "url": "https://api.github.com/repos/symfony/mailer/zipball/01b846f48e53ee4096692a383637a1fa4d577301", + "reference": "01b846f48e53ee4096692a383637a1fa4d577301", "shasum": "" }, "require": { @@ -3167,7 +3281,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.4.31" + "source": "https://github.com/symfony/mailer/tree/v6.4.34" }, "funding": [ { @@ -3187,20 +3301,20 @@ "type": "tidelift" } ], - "time": "2025-12-12T07:33:25+00:00" + "time": "2026-02-24T09:34:36+00:00" }, { "name": "symfony/mime", - "version": "v6.4.32", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "7409686879ca36c09fc970a5fa8ff6e93504dba4" + "reference": "9c31726137c70798f815fb98293ffb8a2a47694c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/7409686879ca36c09fc970a5fa8ff6e93504dba4", - "reference": "7409686879ca36c09fc970a5fa8ff6e93504dba4", + "url": "https://api.github.com/repos/symfony/mime/zipball/9c31726137c70798f815fb98293ffb8a2a47694c", + "reference": "9c31726137c70798f815fb98293ffb8a2a47694c", "shasum": "" }, "require": { @@ -3256,7 +3370,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.32" + "source": "https://github.com/symfony/mime/tree/v6.4.36" }, "funding": [ { @@ -3276,20 +3390,167 @@ "type": "tidelift" } ], - "time": "2026-01-04T11:53:14+00:00" + "time": "2026-03-30T09:31:23+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "name": "symfony/options-resolver", + "version": "v6.4.30", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "url": "https://github.com/symfony/options-resolver.git", + "reference": "eeaa8cabe54c7b3516938c72a4a161c0cc80a34f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/eeaa8cabe54c7b3516938c72a4a161c0cc80a34f", + "reference": "eeaa8cabe54c7b3516938c72a4a161c0cc80a34f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v6.4.30" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-11-12T13:06:53+00:00" + }, + { + "name": "symfony/password-hasher", + "version": "v6.4.32", + "source": { + "type": "git", + "url": "https://github.com/symfony/password-hasher.git", + "reference": "fbdfa5a2ca218ec8bb9029517426df2d780bdba9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/fbdfa5a2ca218ec8bb9029517426df2d780bdba9", + "reference": "fbdfa5a2ca218ec8bb9029517426df2d780bdba9", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "conflict": { + "symfony/security-core": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/security-core": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PasswordHasher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Robin Chalas", + "email": "robin.chalas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides password hashing utilities", + "homepage": "https://symfony.com", + "keywords": [ + "hashing", + "password" + ], + "support": { + "source": "https://github.com/symfony/password-hasher/tree/v6.4.32" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-01T21:24:53+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.36.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -3339,7 +3600,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.36.0" }, "funding": [ { @@ -3359,20 +3620,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/ad1b7b9092976d6c948b8a187cec9faaea9ec1df", + "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df", "shasum": "" }, "require": { @@ -3421,7 +3682,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.36.0" }, "funding": [ { @@ -3441,11 +3702,99 @@ "type": "tidelift" } ], - "time": "2025-06-27T09:58:17+00:00" + "time": "2026-04-10T16:19:22+00:00" + }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.36.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "3510b63d07376b04e57e27e82607d468bb134f78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/3510b63d07376b04e57e27e82607d468bb134f78", + "reference": "3510b63d07376b04e57e27e82607d468bb134f78", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance and support of other locales than \"en\"" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Icu\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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 for intl's ICU-related data and classes", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "icu", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.36.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-04-10T16:50:15+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -3508,7 +3857,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.36.0" }, "funding": [ { @@ -3532,7 +3881,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -3593,7 +3942,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.36.0" }, "funding": [ { @@ -3617,16 +3966,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", "shasum": "" }, "require": { @@ -3678,7 +4027,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.36.0" }, "funding": [ { @@ -3698,20 +4047,20 @@ "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.33.0", + "version": "v1.36.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/3600c2cb22399e25bb226e4a135ce91eeb2a6149", + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149", "shasum": "" }, "require": { @@ -3758,7 +4107,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.36.0" }, "funding": [ { @@ -3778,20 +4127,191 @@ "type": "tidelift" } ], - "time": "2025-07-08T02:45:35+00:00" + "time": "2026-04-10T17:25:58+00:00" }, { - "name": "symfony/routing", + "name": "symfony/property-access", "version": "v6.4.32", "source": { "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "0dc6253e864e71b486e8ba4970a56ab849106ebe" + "url": "https://github.com/symfony/property-access.git", + "reference": "6dfa655ac9e9860c05cabb287f34da86b18c237e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0dc6253e864e71b486e8ba4970a56ab849106ebe", - "reference": "0dc6253e864e71b486e8ba4970a56ab849106ebe", + "url": "https://api.github.com/repos/symfony/property-access/zipball/6dfa655ac9e9860c05cabb287f34da86b18c237e", + "reference": "6dfa655ac9e9860c05cabb287f34da86b18c237e", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4" + }, + "require-dev": { + "symfony/cache": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyAccess\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides functions to read and write from/to an object or array using a simple string notation", + "homepage": "https://symfony.com", + "keywords": [ + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" + ], + "support": { + "source": "https://github.com/symfony/property-access/tree/v6.4.32" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-05T08:25:17+00:00" + }, + { + "name": "symfony/property-info", + "version": "v6.4.34", + "source": { + "type": "git", + "url": "https://github.com/symfony/property-info.git", + "reference": "916455e4c9dcddbebfd101f29d7983841c3564e0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/property-info/zipball/916455e4c9dcddbebfd101f29d7983841c3564e0", + "reference": "916455e4c9dcddbebfd101f29d7983841c3564e0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "doctrine/annotations": "<1.12", + "phpdocumentor/reflection-docblock": "<5.2|>=6", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/cache": "<5.4", + "symfony/dependency-injection": "<5.4|>=6.0,<6.4", + "symfony/serializer": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.12|^2", + "phpdocumentor/reflection-docblock": "^5.2", + "phpstan/phpdoc-parser": "^1.0|^2.0", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/serializer": "^5.4|^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\PropertyInfo\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "dunglas@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Extracts information about PHP class' properties using metadata of popular sources", + "homepage": "https://symfony.com", + "keywords": [ + "doctrine", + "phpdoc", + "property", + "symfony", + "type", + "validator" + ], + "support": { + "source": "https://github.com/symfony/property-info/tree/v6.4.34" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-02-13T09:42:46+00:00" + }, + { + "name": "symfony/routing", + "version": "v6.4.34", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "5ab3a3e1a03535ec5ca6ce2d39e4369a1096ae47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/5ab3a3e1a03535ec5ca6ce2d39e4369a1096ae47", + "reference": "5ab3a3e1a03535ec5ca6ce2d39e4369a1096ae47", "shasum": "" }, "require": { @@ -3845,7 +4365,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.32" + "source": "https://github.com/symfony/routing/tree/v6.4.34" }, "funding": [ { @@ -3865,7 +4385,7 @@ "type": "tidelift" } ], - "time": "2026-01-12T08:31:19+00:00" + "time": "2026-02-24T17:34:50+00:00" }, { "name": "symfony/runtime", @@ -3950,6 +4470,168 @@ ], "time": "2025-12-05T10:55:13+00:00" }, + { + "name": "symfony/security-core", + "version": "v6.4.36", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-core.git", + "reference": "1b7db28bcc3655543abfe58764025aef563705cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-core/zipball/1b7db28bcc3655543abfe58764025aef563705cd", + "reference": "1b7db28bcc3655543abfe58764025aef563705cd", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/event-dispatcher-contracts": "^2.5|^3", + "symfony/password-hasher": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/event-dispatcher": "<5.4", + "symfony/http-foundation": "<5.4", + "symfony/ldap": "<5.4", + "symfony/security-guard": "<5.4", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", + "symfony/validator": "<5.4" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "psr/container": "^1.1|^2.0", + "psr/log": "^1|^2|^3", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/ldap": "^5.4|^6.0|^7.0", + "symfony/string": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", + "symfony/validator": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Core\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - Core Library", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-core/tree/v6.4.36" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-31T01:40:43+00:00" + }, + { + "name": "symfony/security-csrf", + "version": "v6.4.31", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-csrf.git", + "reference": "52f62836fcb19cd351ef3a2aa9cf61a489e8990f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/52f62836fcb19cd351ef3a2aa9cf61a489e8990f", + "reference": "52f62836fcb19cd351ef3a2aa9cf61a489e8990f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/security-core": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/http-foundation": "<5.4" + }, + "require-dev": { + "symfony/http-foundation": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Security\\Csrf\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Security Component - CSRF Library", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/security-csrf/tree/v6.4.31" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-12-17T22:32:13+00:00" + }, { "name": "symfony/service-contracts", "version": "v3.6.1", @@ -4039,16 +4721,16 @@ }, { "name": "symfony/string", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "50590a057841fa6bf69d12eceffce3465b9e32cb" + "reference": "2adaf4106f2ef4c67271971bde6d3fe0a6936432" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/50590a057841fa6bf69d12eceffce3465b9e32cb", - "reference": "50590a057841fa6bf69d12eceffce3465b9e32cb", + "url": "https://api.github.com/repos/symfony/string/zipball/2adaf4106f2ef4c67271971bde6d3fe0a6936432", + "reference": "2adaf4106f2ef4c67271971bde6d3fe0a6936432", "shasum": "" }, "require": { @@ -4104,7 +4786,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.30" + "source": "https://github.com/symfony/string/tree/v6.4.34" }, "funding": [ { @@ -4124,7 +4806,7 @@ "type": "tidelift" } ], - "time": "2025-11-21T18:03:05+00:00" + "time": "2026-02-08T20:44:54+00:00" }, { "name": "symfony/translation-contracts", @@ -4210,16 +4892,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v6.4.32", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "1dcf980dd4f79885b986befdeb1c1bc0d6aedfc8" + "reference": "3ae963a108fd6fc14d09a7fe5e41fe64d8ac11ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/1dcf980dd4f79885b986befdeb1c1bc0d6aedfc8", - "reference": "1dcf980dd4f79885b986befdeb1c1bc0d6aedfc8", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/3ae963a108fd6fc14d09a7fe5e41fe64d8ac11ba", + "reference": "3ae963a108fd6fc14d09a7fe5e41fe64d8ac11ba", "shasum": "" }, "require": { @@ -4299,7 +4981,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.32" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.36" }, "funding": [ { @@ -4319,7 +5001,7 @@ "type": "tidelift" } ], - "time": "2026-01-03T23:03:08+00:00" + "time": "2026-03-30T09:31:23+00:00" }, { "name": "symfony/twig-bundle", @@ -4410,17 +5092,118 @@ "time": "2026-01-05T12:44:39+00:00" }, { - "name": "symfony/var-dumper", - "version": "v6.4.32", + "name": "symfony/validator", + "version": "v6.4.36", "source": { "type": "git", - "url": "https://github.com/symfony/var-dumper.git", - "reference": "131fc9915e0343052af5ed5040401b481ca192aa" + "url": "https://github.com/symfony/validator.git", + "reference": "14921e87b2bd69dfbd9757cdb1c6974a1316aac5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/131fc9915e0343052af5ed5040401b481ca192aa", - "reference": "131fc9915e0343052af5ed5040401b481ca192aa", + "url": "https://api.github.com/repos/symfony/validator/zipball/14921e87b2bd69dfbd9757cdb1c6974a1316aac5", + "reference": "14921e87b2bd69dfbd9757cdb1c6974a1316aac5", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php83": "^1.27", + "symfony/translation-contracts": "^2.5|^3" + }, + "conflict": { + "doctrine/annotations": "<1.13", + "doctrine/lexer": "<1.1", + "symfony/dependency-injection": "<5.4", + "symfony/expression-language": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/intl": "<5.4", + "symfony/property-info": "<5.4", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", + "symfony/yaml": "<5.4" + }, + "require-dev": { + "doctrine/annotations": "^1.13|^2", + "egulias/email-validator": "^2.1.10|^3|^4", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "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/http-client": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", + "symfony/yaml": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Validator\\": "" + }, + "exclude-from-classmap": [ + "/Tests/", + "/Resources/bin/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to validate values", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/validator/tree/v6.4.36" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-26T15:58:46+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v6.4.36", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "7c8ad9ce4faf6c8a99948e70ce02b601a0439782" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7c8ad9ce4faf6c8a99948e70ce02b601a0439782", + "reference": "7c8ad9ce4faf6c8a99948e70ce02b601a0439782", "shasum": "" }, "require": { @@ -4475,7 +5258,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.32" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.36" }, "funding": [ { @@ -4495,20 +5278,20 @@ "type": "tidelift" } ], - "time": "2026-01-01T13:34:06+00:00" + "time": "2026-03-30T15:36:00+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.26", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc" + "reference": "f9c4a9695a9e2bbc65c920e147d8d7ae28f8d79a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/466fcac5fa2e871f83d31173f80e9c2684743bfc", - "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f9c4a9695a9e2bbc65c920e147d8d7ae28f8d79a", + "reference": "f9c4a9695a9e2bbc65c920e147d8d7ae28f8d79a", "shasum": "" }, "require": { @@ -4556,7 +5339,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.26" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.36" }, "funding": [ { @@ -4576,20 +5359,20 @@ "type": "tidelift" } ], - "time": "2025-09-11T09:57:09+00:00" + "time": "2026-03-10T15:06:19+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "8207ae83da19ee3748d6d4f567b4d9a7c656e331" + "reference": "7bca30dabed7900a08c5ad4f1d6483f881a64d0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/8207ae83da19ee3748d6d4f567b4d9a7c656e331", - "reference": "8207ae83da19ee3748d6d4f567b4d9a7c656e331", + "url": "https://api.github.com/repos/symfony/yaml/zipball/7bca30dabed7900a08c5ad4f1d6483f881a64d0f", + "reference": "7bca30dabed7900a08c5ad4f1d6483f881a64d0f", "shasum": "" }, "require": { @@ -4632,7 +5415,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.30" + "source": "https://github.com/symfony/yaml/tree/v6.4.34" }, "funding": [ { @@ -4652,20 +5435,20 @@ "type": "tidelift" } ], - "time": "2025-12-02T11:50:18+00:00" + "time": "2026-02-06T18:32:11+00:00" }, { "name": "tecnickcom/tcpdf", - "version": "6.10.1", + "version": "6.11.2", "source": { "type": "git", "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "7a2701251e5d52fc3d508fd71704683eb54f5939" + "reference": "e1e2ade18e574e963473f53271591edd8c0033ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/7a2701251e5d52fc3d508fd71704683eb54f5939", - "reference": "7a2701251e5d52fc3d508fd71704683eb54f5939", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/e1e2ade18e574e963473f53271591edd8c0033ec", + "reference": "e1e2ade18e574e963473f53271591edd8c0033ec", "shasum": "" }, "require": { @@ -4715,7 +5498,7 @@ ], "support": { "issues": "https://github.com/tecnickcom/TCPDF/issues", - "source": "https://github.com/tecnickcom/TCPDF/tree/6.10.1" + "source": "https://github.com/tecnickcom/TCPDF/tree/6.11.2" }, "funding": [ { @@ -4723,20 +5506,20 @@ "type": "custom" } ], - "time": "2025-11-21T10:58:21+00:00" + "time": "2026-03-03T08:58:10+00:00" }, { "name": "thenetworg/oauth2-azure", - "version": "v2.2.4", + "version": "v2.2.5", "source": { "type": "git", "url": "https://github.com/TheNetworg/oauth2-azure.git", - "reference": "a897d60b6b127daa2f27b1b4e62e7af40829d02f" + "reference": "06f1aa023e18cc3ea80df6410c7c2dc5502a3655" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/TheNetworg/oauth2-azure/zipball/a897d60b6b127daa2f27b1b4e62e7af40829d02f", - "reference": "a897d60b6b127daa2f27b1b4e62e7af40829d02f", + "url": "https://api.github.com/repos/TheNetworg/oauth2-azure/zipball/06f1aa023e18cc3ea80df6410c7c2dc5502a3655", + "reference": "06f1aa023e18cc3ea80df6410c7c2dc5502a3655", "shasum": "" }, "require": { @@ -4781,22 +5564,22 @@ ], "support": { "issues": "https://github.com/TheNetworg/oauth2-azure/issues", - "source": "https://github.com/TheNetworg/oauth2-azure/tree/v2.2.4" + "source": "https://github.com/TheNetworg/oauth2-azure/tree/v2.2.5" }, - "time": "2026-01-29T12:43:59+00:00" + "time": "2026-02-26T08:05:57+00:00" }, { "name": "twig/twig", - "version": "v3.23.0", + "version": "v3.24.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9" + "reference": "a6769aefb305efef849dc25c9fd1653358c148f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", - "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a6769aefb305efef849dc25c9fd1653358c148f0", + "reference": "a6769aefb305efef849dc25c9fd1653358c148f0", "shasum": "" }, "require": { @@ -4806,7 +5589,8 @@ "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { - "phpstan/phpstan": "^2.0", + "php-cs-fixer/shim": "^3.0@stable", + "phpstan/phpstan": "^2.0@stable", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, @@ -4850,7 +5634,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.23.0" + "source": "https://github.com/twigphp/Twig/tree/v3.24.0" }, "funding": [ { @@ -4862,22 +5646,22 @@ "type": "tidelift" } ], - "time": "2026-01-23T21:00:41+00:00" + "time": "2026-03-17T21:31:11+00:00" } ], "packages-dev": [ { "name": "symfony/debug-bundle", - "version": "v6.4.27", + "version": "v6.4.35", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "21a61c55192d558a6b81cdb12e8c010fc9474fe0" + "reference": "eb79084c2c9778559b21f61cb1507cbd580cc6e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/21a61c55192d558a6b81cdb12e8c010fc9474fe0", - "reference": "21a61c55192d558a6b81cdb12e8c010fc9474fe0", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/eb79084c2c9778559b21f61cb1507cbd580cc6e1", + "reference": "eb79084c2c9778559b21f61cb1507cbd580cc6e1", "shasum": "" }, "require": { @@ -4922,7 +5706,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.27" + "source": "https://github.com/symfony/debug-bundle/tree/v6.4.35" }, "funding": [ { @@ -4942,7 +5726,7 @@ "type": "tidelift" } ], - "time": "2025-10-11T17:35:31+00:00" + "time": "2026-03-02T09:25:10+00:00" }, { "name": "symfony/stopwatch", @@ -5012,16 +5796,16 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.32", + "version": "v6.4.36", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "011f59e3f3d20f60d11b4e78b8dc63504f56e145" + "reference": "6f75b4c748886c8e04a3674225d00eaa51f3842d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/011f59e3f3d20f60d11b4e78b8dc63504f56e145", - "reference": "011f59e3f3d20f60d11b4e78b8dc63504f56e145", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/6f75b4c748886c8e04a3674225d00eaa51f3842d", + "reference": "6f75b4c748886c8e04a3674225d00eaa51f3842d", "shasum": "" }, "require": { @@ -5074,7 +5858,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.32" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.36" }, "funding": [ { @@ -5094,19 +5878,20 @@ "type": "tidelift" } ], - "time": "2026-01-06T09:13:42+00:00" + "time": "2026-03-17T09:05:06+00:00" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": { "apereo/phpcas": 20, + "nikic/php-parser": 20, "scssphp/scssphp": 20 }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=8.1.0 <8.5.0", + "php": ">=8.2.0 <8.5.0", "ext-ctype": "*", "ext-dom": "*", "ext-gd": "*", @@ -5117,7 +5902,7 @@ }, "platform-dev": {}, "platform-overrides": { - "php": "8.1.0" + "php": "8.2.0" }, "plugin-api-version": "2.9.0" } diff --git a/lib/autoload_runtime.php b/lib/autoload_runtime.php new file mode 100644 index 000000000..6b5344587 --- /dev/null +++ b/lib/autoload_runtime.php @@ -0,0 +1,31 @@ + 'resources/symfony/.env', + 'project_dir' => dirname(__DIR__, 1), +]); + +[$app, $args] = $runtime + ->getResolver($app) + ->resolve(); + +$app = $app(...$args); + +exit( + $runtime + ->getRunner($app) + ->run() +); diff --git a/lib/composer/autoload_classmap.php b/lib/composer/autoload_classmap.php index a213032b6..52b87f481 100644 --- a/lib/composer/autoload_classmap.php +++ b/lib/composer/autoload_classmap.php @@ -960,6 +960,7 @@ return array( 'IntervalExpression' => $baseDir . '/core/oql/expression.class.inc.php', 'IntervalOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php', 'IntlDateFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/Resources/stubs/IntlDateFormatter.php', + 'IntlListFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/Resources/stubs/IntlListFormatter.php', 'Introspection' => $baseDir . '/core/introspection.class.inc.php', 'InvalidConfigParamException' => $baseDir . '/application/exceptions/InvalidConfigParamException.php', 'InvalidExternalKeyValueException' => $baseDir . '/application/exceptions/InvalidExternalKeyValueException.php', @@ -1606,6 +1607,11 @@ return array( 'Symfony\\Bridge\\Twig\\TokenParser\\TransTokenParser' => $vendorDir . '/symfony/twig-bridge/TokenParser/TransTokenParser.php', 'Symfony\\Bridge\\Twig\\Translation\\TwigExtractor' => $vendorDir . '/symfony/twig-bridge/Translation/TwigExtractor.php', 'Symfony\\Bridge\\Twig\\UndefinedCallableHandler' => $vendorDir . '/symfony/twig-bridge/UndefinedCallableHandler.php', + 'Symfony\\Bundle\\DebugBundle\\Command\\ServerDumpPlaceholderCommand' => $vendorDir . '/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php', + 'Symfony\\Bundle\\DebugBundle\\DebugBundle' => $vendorDir . '/symfony/debug-bundle/DebugBundle.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\Compiler\\DumpDataCollectorPass' => $vendorDir . '/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\Configuration' => $vendorDir . '/symfony/debug-bundle/DependencyInjection/Configuration.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\DebugExtension' => $vendorDir . '/symfony/debug-bundle/DependencyInjection/DebugExtension.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => $vendorDir . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php', @@ -1809,6 +1815,7 @@ return array( 'Symfony\\Component\\Cache\\Traits\\Relay\\Relay121Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay121Trait.php', 'Symfony\\Component\\Cache\\Traits\\Relay\\Relay12Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay12Trait.php', 'Symfony\\Component\\Cache\\Traits\\Relay\\Relay20Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay20Trait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\Relay21Trait' => $vendorDir . '/symfony/cache/Traits/Relay/Relay21Trait.php', 'Symfony\\Component\\Cache\\Traits\\Relay\\SwapdbTrait' => $vendorDir . '/symfony/cache/Traits/Relay/SwapdbTrait.php', 'Symfony\\Component\\Config\\Builder\\ClassBuilder' => $vendorDir . '/symfony/config/Builder/ClassBuilder.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => $vendorDir . '/symfony/config/Builder/ConfigBuilderGenerator.php', @@ -2257,6 +2264,7 @@ return array( 'Symfony\\Component\\Dotenv\\Exception\\FormatException' => $vendorDir . '/symfony/dotenv/Exception/FormatException.php', 'Symfony\\Component\\Dotenv\\Exception\\FormatExceptionContext' => $vendorDir . '/symfony/dotenv/Exception/FormatExceptionContext.php', 'Symfony\\Component\\Dotenv\\Exception\\PathException' => $vendorDir . '/symfony/dotenv/Exception/PathException.php', + 'Symfony\\Component\\Dotenv\\Exception\\VariableCircularReferenceException' => $vendorDir . '/symfony/dotenv/Exception/VariableCircularReferenceException.php', 'Symfony\\Component\\ErrorHandler\\BufferingLogger' => $vendorDir . '/symfony/error-handler/BufferingLogger.php', 'Symfony\\Component\\ErrorHandler\\Debug' => $vendorDir . '/symfony/error-handler/Debug.php', 'Symfony\\Component\\ErrorHandler\\DebugClassLoader' => $vendorDir . '/symfony/error-handler/DebugClassLoader.php', @@ -3074,6 +3082,21 @@ return array( 'Symfony\\Component\\Routing\\RouteCompilerInterface' => $vendorDir . '/symfony/routing/RouteCompilerInterface.php', 'Symfony\\Component\\Routing\\Router' => $vendorDir . '/symfony/routing/Router.php', 'Symfony\\Component\\Routing\\RouterInterface' => $vendorDir . '/symfony/routing/RouterInterface.php', + 'Symfony\\Component\\Runtime\\GenericRuntime' => $vendorDir . '/symfony/runtime/GenericRuntime.php', + 'Symfony\\Component\\Runtime\\Internal\\BasicErrorHandler' => $vendorDir . '/symfony/runtime/Internal/BasicErrorHandler.php', + 'Symfony\\Component\\Runtime\\Internal\\ComposerPlugin' => $vendorDir . '/symfony/runtime/Internal/ComposerPlugin.php', + 'Symfony\\Component\\Runtime\\Internal\\MissingDotenv' => $vendorDir . '/symfony/runtime/Internal/MissingDotenv.php', + 'Symfony\\Component\\Runtime\\Internal\\SymfonyErrorHandler' => $vendorDir . '/symfony/runtime/Internal/SymfonyErrorHandler.php', + 'Symfony\\Component\\Runtime\\ResolverInterface' => $vendorDir . '/symfony/runtime/ResolverInterface.php', + 'Symfony\\Component\\Runtime\\Resolver\\ClosureResolver' => $vendorDir . '/symfony/runtime/Resolver/ClosureResolver.php', + 'Symfony\\Component\\Runtime\\Resolver\\DebugClosureResolver' => $vendorDir . '/symfony/runtime/Resolver/DebugClosureResolver.php', + 'Symfony\\Component\\Runtime\\RunnerInterface' => $vendorDir . '/symfony/runtime/RunnerInterface.php', + 'Symfony\\Component\\Runtime\\Runner\\ClosureRunner' => $vendorDir . '/symfony/runtime/Runner/ClosureRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\ConsoleApplicationRunner' => $vendorDir . '/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner' => $vendorDir . '/symfony/runtime/Runner/Symfony/HttpKernelRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\ResponseRunner' => $vendorDir . '/symfony/runtime/Runner/Symfony/ResponseRunner.php', + 'Symfony\\Component\\Runtime\\RuntimeInterface' => $vendorDir . '/symfony/runtime/RuntimeInterface.php', + 'Symfony\\Component\\Runtime\\SymfonyRuntime' => $vendorDir . '/symfony/runtime/SymfonyRuntime.php', 'Symfony\\Component\\Security\\Core\\AuthenticationEvents' => $vendorDir . '/symfony/security-core/AuthenticationEvents.php', 'Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolver' => $vendorDir . '/symfony/security-core/Authentication/AuthenticationTrustResolver.php', 'Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface' => $vendorDir . '/symfony/security-core/Authentication/AuthenticationTrustResolverInterface.php', @@ -3565,6 +3588,7 @@ return array( 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\RuntimeException' => $vendorDir . '/symfony/polyfill-intl-icu/Exception/RuntimeException.php', 'Symfony\\Polyfill\\Intl\\Icu\\Icu' => $vendorDir . '/symfony/polyfill-intl-icu/Icu.php', 'Symfony\\Polyfill\\Intl\\Icu\\IntlDateFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/IntlDateFormatter.php', + 'Symfony\\Polyfill\\Intl\\Icu\\IntlListFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/IntlListFormatter.php', 'Symfony\\Polyfill\\Intl\\Icu\\Locale' => $vendorDir . '/symfony/polyfill-intl-icu/Locale.php', 'Symfony\\Polyfill\\Intl\\Icu\\NumberFormatter' => $vendorDir . '/symfony/polyfill-intl-icu/NumberFormatter.php', 'Symfony\\Polyfill\\Intl\\Idn\\Idn' => $vendorDir . '/symfony/polyfill-intl-idn/Idn.php', @@ -3574,6 +3598,13 @@ return array( 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/symfony/polyfill-mbstring/Mbstring.php', 'Symfony\\Polyfill\\Php83\\Php83' => $vendorDir . '/symfony/polyfill-php83/Php83.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\ApplicationRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/ApplicationRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Command\\CommandRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/Command/CommandRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Input\\InputInterfaceRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Output\\OutputInterfaceRuntime' => $vendorDir . '/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpFoundation\\RequestRuntime' => $vendorDir . '/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpFoundation\\ResponseRuntime' => $vendorDir . '/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpKernel\\HttpKernelInterfaceRuntime' => $vendorDir . '/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php', 'SynchroExceptionNotStarted' => $baseDir . '/application/exceptions/SynchroExceptionNotStarted.php', 'System' => $vendorDir . '/pear/pear-core-minimal/src/System.php', 'TCPDF' => $vendorDir . '/tecnickcom/tcpdf/tcpdf.php', diff --git a/lib/composer/autoload_files.php b/lib/composer/autoload_files.php index 26e7e2345..b0244afb9 100644 --- a/lib/composer/autoload_files.php +++ b/lib/composer/autoload_files.php @@ -10,8 +10,8 @@ return array( '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php', - 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php', + 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php', '89efb1254ef2d1c5d80096acd12c4098' => $vendorDir . '/twig/twig/src/Resources/core.php', 'ffecb95d45175fd40f75be8a23b34f90' => $vendorDir . '/twig/twig/src/Resources/debug.php', 'c7baa00073ee9c61edf148c51917cfb4' => $vendorDir . '/twig/twig/src/Resources/escaper.php', diff --git a/lib/composer/autoload_psr4.php b/lib/composer/autoload_psr4.php index d71f96f11..be2d5f112 100644 --- a/lib/composer/autoload_psr4.php +++ b/lib/composer/autoload_psr4.php @@ -8,6 +8,7 @@ $baseDir = dirname($vendorDir); return array( 'Twig\\' => array($vendorDir . '/twig/twig/src'), 'TheNetworg\\OAuth2\\Client\\' => array($vendorDir . '/thenetworg/oauth2-azure/src'), + 'Symfony\\Runtime\\Symfony\\Component\\' => array($vendorDir . '/symfony/runtime/Internal'), 'Symfony\\Polyfill\\Php83\\' => array($vendorDir . '/symfony/polyfill-php83'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'), @@ -27,6 +28,7 @@ return array( 'Symfony\\Component\\Stopwatch\\' => array($vendorDir . '/symfony/stopwatch'), 'Symfony\\Component\\Security\\Csrf\\' => array($vendorDir . '/symfony/security-csrf'), 'Symfony\\Component\\Security\\Core\\' => array($vendorDir . '/symfony/security-core'), + 'Symfony\\Component\\Runtime\\' => array($vendorDir . '/symfony/runtime'), 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), 'Symfony\\Component\\PropertyInfo\\' => array($vendorDir . '/symfony/property-info'), 'Symfony\\Component\\PropertyAccess\\' => array($vendorDir . '/symfony/property-access'), @@ -50,6 +52,7 @@ return array( 'Symfony\\Bundle\\WebProfilerBundle\\' => array($vendorDir . '/symfony/web-profiler-bundle'), 'Symfony\\Bundle\\TwigBundle\\' => array($vendorDir . '/symfony/twig-bundle'), 'Symfony\\Bundle\\FrameworkBundle\\' => array($vendorDir . '/symfony/framework-bundle'), + 'Symfony\\Bundle\\DebugBundle\\' => array($vendorDir . '/symfony/debug-bundle'), 'Symfony\\Bridge\\Twig\\' => array($vendorDir . '/symfony/twig-bridge'), 'Soundasleep\\' => array($vendorDir . '/soundasleep/html2text/src'), 'ScssPhp\\ScssPhp\\' => array($vendorDir . '/scssphp/scssphp/src'), diff --git a/lib/composer/autoload_static.php b/lib/composer/autoload_static.php index 039c7bee0..0837e69a7 100644 --- a/lib/composer/autoload_static.php +++ b/lib/composer/autoload_static.php @@ -11,8 +11,8 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php', - 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php', + 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php', '89efb1254ef2d1c5d80096acd12c4098' => __DIR__ . '/..' . '/twig/twig/src/Resources/core.php', 'ffecb95d45175fd40f75be8a23b34f90' => __DIR__ . '/..' . '/twig/twig/src/Resources/debug.php', 'c7baa00073ee9c61edf148c51917cfb4' => __DIR__ . '/..' . '/twig/twig/src/Resources/escaper.php', @@ -35,6 +35,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 ), 'S' => array ( + 'Symfony\\Runtime\\Symfony\\Component\\' => 34, 'Symfony\\Polyfill\\Php83\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33, @@ -54,6 +55,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'Symfony\\Component\\Stopwatch\\' => 28, 'Symfony\\Component\\Security\\Csrf\\' => 32, 'Symfony\\Component\\Security\\Core\\' => 32, + 'Symfony\\Component\\Runtime\\' => 26, 'Symfony\\Component\\Routing\\' => 26, 'Symfony\\Component\\PropertyInfo\\' => 31, 'Symfony\\Component\\PropertyAccess\\' => 33, @@ -77,6 +79,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'Symfony\\Bundle\\WebProfilerBundle\\' => 33, 'Symfony\\Bundle\\TwigBundle\\' => 26, 'Symfony\\Bundle\\FrameworkBundle\\' => 31, + 'Symfony\\Bundle\\DebugBundle\\' => 27, 'Symfony\\Bridge\\Twig\\' => 20, 'Soundasleep\\' => 12, 'ScssPhp\\ScssPhp\\' => 16, @@ -126,6 +129,10 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 array ( 0 => __DIR__ . '/..' . '/thenetworg/oauth2-azure/src', ), + 'Symfony\\Runtime\\Symfony\\Component\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/runtime/Internal', + ), 'Symfony\\Polyfill\\Php83\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-php83', @@ -202,6 +209,10 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 array ( 0 => __DIR__ . '/..' . '/symfony/security-core', ), + 'Symfony\\Component\\Runtime\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/runtime', + ), 'Symfony\\Component\\Routing\\' => array ( 0 => __DIR__ . '/..' . '/symfony/routing', @@ -294,6 +305,10 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 array ( 0 => __DIR__ . '/..' . '/symfony/framework-bundle', ), + 'Symfony\\Bundle\\DebugBundle\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/debug-bundle', + ), 'Symfony\\Bridge\\Twig\\' => array ( 0 => __DIR__ . '/..' . '/symfony/twig-bridge', @@ -1346,6 +1361,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'IntervalExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php', 'IntervalOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php', 'IntlDateFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Resources/stubs/IntlDateFormatter.php', + 'IntlListFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Resources/stubs/IntlListFormatter.php', 'Introspection' => __DIR__ . '/../..' . '/core/introspection.class.inc.php', 'InvalidConfigParamException' => __DIR__ . '/../..' . '/application/exceptions/InvalidConfigParamException.php', 'InvalidExternalKeyValueException' => __DIR__ . '/../..' . '/application/exceptions/InvalidExternalKeyValueException.php', @@ -1992,6 +2008,11 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'Symfony\\Bridge\\Twig\\TokenParser\\TransTokenParser' => __DIR__ . '/..' . '/symfony/twig-bridge/TokenParser/TransTokenParser.php', 'Symfony\\Bridge\\Twig\\Translation\\TwigExtractor' => __DIR__ . '/..' . '/symfony/twig-bridge/Translation/TwigExtractor.php', 'Symfony\\Bridge\\Twig\\UndefinedCallableHandler' => __DIR__ . '/..' . '/symfony/twig-bridge/UndefinedCallableHandler.php', + 'Symfony\\Bundle\\DebugBundle\\Command\\ServerDumpPlaceholderCommand' => __DIR__ . '/..' . '/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php', + 'Symfony\\Bundle\\DebugBundle\\DebugBundle' => __DIR__ . '/..' . '/symfony/debug-bundle/DebugBundle.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\Compiler\\DumpDataCollectorPass' => __DIR__ . '/..' . '/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\Configuration' => __DIR__ . '/..' . '/symfony/debug-bundle/DependencyInjection/Configuration.php', + 'Symfony\\Bundle\\DebugBundle\\DependencyInjection\\DebugExtension' => __DIR__ . '/..' . '/symfony/debug-bundle/DependencyInjection/DebugExtension.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AbstractPhpFileCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AbstractPhpFileCacheWarmer.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\AnnotationsCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/AnnotationsCacheWarmer.php', 'Symfony\\Bundle\\FrameworkBundle\\CacheWarmer\\CachePoolClearerCacheWarmer' => __DIR__ . '/..' . '/symfony/framework-bundle/CacheWarmer/CachePoolClearerCacheWarmer.php', @@ -2195,6 +2216,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'Symfony\\Component\\Cache\\Traits\\Relay\\Relay121Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay121Trait.php', 'Symfony\\Component\\Cache\\Traits\\Relay\\Relay12Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay12Trait.php', 'Symfony\\Component\\Cache\\Traits\\Relay\\Relay20Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay20Trait.php', + 'Symfony\\Component\\Cache\\Traits\\Relay\\Relay21Trait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/Relay21Trait.php', 'Symfony\\Component\\Cache\\Traits\\Relay\\SwapdbTrait' => __DIR__ . '/..' . '/symfony/cache/Traits/Relay/SwapdbTrait.php', 'Symfony\\Component\\Config\\Builder\\ClassBuilder' => __DIR__ . '/..' . '/symfony/config/Builder/ClassBuilder.php', 'Symfony\\Component\\Config\\Builder\\ConfigBuilderGenerator' => __DIR__ . '/..' . '/symfony/config/Builder/ConfigBuilderGenerator.php', @@ -2643,6 +2665,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'Symfony\\Component\\Dotenv\\Exception\\FormatException' => __DIR__ . '/..' . '/symfony/dotenv/Exception/FormatException.php', 'Symfony\\Component\\Dotenv\\Exception\\FormatExceptionContext' => __DIR__ . '/..' . '/symfony/dotenv/Exception/FormatExceptionContext.php', 'Symfony\\Component\\Dotenv\\Exception\\PathException' => __DIR__ . '/..' . '/symfony/dotenv/Exception/PathException.php', + 'Symfony\\Component\\Dotenv\\Exception\\VariableCircularReferenceException' => __DIR__ . '/..' . '/symfony/dotenv/Exception/VariableCircularReferenceException.php', 'Symfony\\Component\\ErrorHandler\\BufferingLogger' => __DIR__ . '/..' . '/symfony/error-handler/BufferingLogger.php', 'Symfony\\Component\\ErrorHandler\\Debug' => __DIR__ . '/..' . '/symfony/error-handler/Debug.php', 'Symfony\\Component\\ErrorHandler\\DebugClassLoader' => __DIR__ . '/..' . '/symfony/error-handler/DebugClassLoader.php', @@ -3460,6 +3483,21 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'Symfony\\Component\\Routing\\RouteCompilerInterface' => __DIR__ . '/..' . '/symfony/routing/RouteCompilerInterface.php', 'Symfony\\Component\\Routing\\Router' => __DIR__ . '/..' . '/symfony/routing/Router.php', 'Symfony\\Component\\Routing\\RouterInterface' => __DIR__ . '/..' . '/symfony/routing/RouterInterface.php', + 'Symfony\\Component\\Runtime\\GenericRuntime' => __DIR__ . '/..' . '/symfony/runtime/GenericRuntime.php', + 'Symfony\\Component\\Runtime\\Internal\\BasicErrorHandler' => __DIR__ . '/..' . '/symfony/runtime/Internal/BasicErrorHandler.php', + 'Symfony\\Component\\Runtime\\Internal\\ComposerPlugin' => __DIR__ . '/..' . '/symfony/runtime/Internal/ComposerPlugin.php', + 'Symfony\\Component\\Runtime\\Internal\\MissingDotenv' => __DIR__ . '/..' . '/symfony/runtime/Internal/MissingDotenv.php', + 'Symfony\\Component\\Runtime\\Internal\\SymfonyErrorHandler' => __DIR__ . '/..' . '/symfony/runtime/Internal/SymfonyErrorHandler.php', + 'Symfony\\Component\\Runtime\\ResolverInterface' => __DIR__ . '/..' . '/symfony/runtime/ResolverInterface.php', + 'Symfony\\Component\\Runtime\\Resolver\\ClosureResolver' => __DIR__ . '/..' . '/symfony/runtime/Resolver/ClosureResolver.php', + 'Symfony\\Component\\Runtime\\Resolver\\DebugClosureResolver' => __DIR__ . '/..' . '/symfony/runtime/Resolver/DebugClosureResolver.php', + 'Symfony\\Component\\Runtime\\RunnerInterface' => __DIR__ . '/..' . '/symfony/runtime/RunnerInterface.php', + 'Symfony\\Component\\Runtime\\Runner\\ClosureRunner' => __DIR__ . '/..' . '/symfony/runtime/Runner/ClosureRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\ConsoleApplicationRunner' => __DIR__ . '/..' . '/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\HttpKernelRunner' => __DIR__ . '/..' . '/symfony/runtime/Runner/Symfony/HttpKernelRunner.php', + 'Symfony\\Component\\Runtime\\Runner\\Symfony\\ResponseRunner' => __DIR__ . '/..' . '/symfony/runtime/Runner/Symfony/ResponseRunner.php', + 'Symfony\\Component\\Runtime\\RuntimeInterface' => __DIR__ . '/..' . '/symfony/runtime/RuntimeInterface.php', + 'Symfony\\Component\\Runtime\\SymfonyRuntime' => __DIR__ . '/..' . '/symfony/runtime/SymfonyRuntime.php', 'Symfony\\Component\\Security\\Core\\AuthenticationEvents' => __DIR__ . '/..' . '/symfony/security-core/AuthenticationEvents.php', 'Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolver' => __DIR__ . '/..' . '/symfony/security-core/Authentication/AuthenticationTrustResolver.php', 'Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationTrustResolverInterface' => __DIR__ . '/..' . '/symfony/security-core/Authentication/AuthenticationTrustResolverInterface.php', @@ -3951,6 +3989,7 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'Symfony\\Polyfill\\Intl\\Icu\\Exception\\RuntimeException' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Exception/RuntimeException.php', 'Symfony\\Polyfill\\Intl\\Icu\\Icu' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Icu.php', 'Symfony\\Polyfill\\Intl\\Icu\\IntlDateFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/IntlDateFormatter.php', + 'Symfony\\Polyfill\\Intl\\Icu\\IntlListFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/IntlListFormatter.php', 'Symfony\\Polyfill\\Intl\\Icu\\Locale' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/Locale.php', 'Symfony\\Polyfill\\Intl\\Icu\\NumberFormatter' => __DIR__ . '/..' . '/symfony/polyfill-intl-icu/NumberFormatter.php', 'Symfony\\Polyfill\\Intl\\Idn\\Idn' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/Idn.php', @@ -3960,6 +3999,13 @@ class ComposerStaticInitfc0e9e9dea11dcbb6272414776c30685 'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Normalizer.php', 'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/Mbstring.php', 'Symfony\\Polyfill\\Php83\\Php83' => __DIR__ . '/..' . '/symfony/polyfill-php83/Php83.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\ApplicationRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/ApplicationRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Command\\CommandRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/Command/CommandRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Input\\InputInterfaceRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\Console\\Output\\OutputInterfaceRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpFoundation\\RequestRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpFoundation\\ResponseRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php', + 'Symfony\\Runtime\\Symfony\\Component\\HttpKernel\\HttpKernelInterfaceRuntime' => __DIR__ . '/..' . '/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php', 'SynchroExceptionNotStarted' => __DIR__ . '/../..' . '/application/exceptions/SynchroExceptionNotStarted.php', 'System' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/System.php', 'TCPDF' => __DIR__ . '/..' . '/tecnickcom/tcpdf/tcpdf.php', diff --git a/lib/composer/installed.json b/lib/composer/installed.json index 66435c1a1..7d46b6603 100644 --- a/lib/composer/installed.json +++ b/lib/composer/installed.json @@ -239,17 +239,17 @@ }, { "name": "firebase/php-jwt", - "version": "v7.0.3", - "version_normalized": "7.0.3.0", + "version": "v7.0.5", + "version_normalized": "7.0.5.0", "source": { "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e" + "url": "https://github.com/googleapis/php-jwt.git", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/28aa0694bcfdfa5e2959c394d5a1ee7a5083629e", - "reference": "28aa0694bcfdfa5e2959c394d5a1ee7a5083629e", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", "shasum": "" }, "require": { @@ -257,6 +257,7 @@ }, "require-dev": { "guzzlehttp/guzzle": "^7.4", + "phpfastcache/phpfastcache": "^9.2", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", @@ -267,7 +268,7 @@ "ext-sodium": "Support EdDSA (Ed25519) signatures", "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" }, - "time": "2026-02-25T22:16:40+00:00", + "time": "2026-04-01T20:38:03+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -298,8 +299,8 @@ "php" ], "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v7.0.3" + "issues": "https://github.com/googleapis/php-jwt/issues", + "source": "https://github.com/googleapis/php-jwt/tree/v7.0.5" }, "install-path": "../firebase/php-jwt" }, @@ -520,17 +521,17 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.8.0", - "version_normalized": "2.8.0.0", + "version": "2.9.0", + "version_normalized": "2.9.0.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884", + "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884", "shasum": "" }, "require": { @@ -546,12 +547,13 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", + "jshttp/mime-db": "1.54.0.1", "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, - "time": "2025-08-23T21:21:41+00:00", + "time": "2026-03-10T16:41:02+00:00", "type": "library", "extra": { "bamarni-bin": { @@ -619,7 +621,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.8.0" + "source": "https://github.com/guzzle/psr7/tree/2.9.0" }, "funding": [ { @@ -707,21 +709,21 @@ }, { "name": "league/oauth2-google", - "version": "4.1.0", - "version_normalized": "4.1.0.0", + "version": "4.2.0", + "version_normalized": "4.2.0.0", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-google.git", - "reference": "8b9bb43740ac6d994aca881a35f7bacbe98c0ffb" + "reference": "72be69505f890ea8b6d4e716f619b3c10a1f5010" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-google/zipball/8b9bb43740ac6d994aca881a35f7bacbe98c0ffb", - "reference": "8b9bb43740ac6d994aca881a35f7bacbe98c0ffb", + "url": "https://api.github.com/repos/thephpleague/oauth2-google/zipball/72be69505f890ea8b6d4e716f619b3c10a1f5010", + "reference": "72be69505f890ea8b6d4e716f619b3c10a1f5010", "shasum": "" }, "require": { - "league/oauth2-client": "^2.0", + "league/oauth2-client": "^2.0 || ^3.0", "php": "^7.3 || ^8.0" }, "require-dev": { @@ -729,7 +731,7 @@ "phpunit/phpunit": "^8.0 || ^9.0", "squizlabs/php_codesniffer": "^3.0" }, - "time": "2025-12-15T12:24:14+00:00", + "time": "2026-03-09T09:36:58+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -759,7 +761,7 @@ ], "support": { "issues": "https://github.com/thephpleague/oauth2-google/issues", - "source": "https://github.com/thephpleague/oauth2-google/tree/4.1.0" + "source": "https://github.com/thephpleague/oauth2-google/tree/4.2.0" }, "install-path": "../league/oauth2-google" }, @@ -770,12 +772,12 @@ "source": { "type": "git", "url": "https://github.com/Combodo/PHP-Parser.git", - "reference": "b2cd0735eb27788d5d41fa3c2cfaa01a593fd7fb" + "reference": "b27e577f70d2114b8ba96105e403017919a8611b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Combodo/PHP-Parser/zipball/b2cd0735eb27788d5d41fa3c2cfaa01a593fd7fb", - "reference": "b2cd0735eb27788d5d41fa3c2cfaa01a593fd7fb", + "url": "https://api.github.com/repos/Combodo/PHP-Parser/zipball/b27e577f70d2114b8ba96105e403017919a8611b", + "reference": "b27e577f70d2114b8ba96105e403017919a8611b", "shasum": "" }, "require": { @@ -788,7 +790,7 @@ "ircmaxell/php-yacc": "^0.0.7", "phpunit/phpunit": "^9.0" }, - "time": "2025-09-18T12:29:15+00:00", + "time": "2026-03-31T15:49:45+00:00", "default-branch": true, "bin": [ "bin/php-parse" @@ -1809,17 +1811,17 @@ }, { "name": "symfony/cache", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "a0a1690543329685c044362c873b78c6de9d4faa" + "reference": "5b94fba945d1f9e7929cffd50e7a17f1ac36f10b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a0a1690543329685c044362c873b78c6de9d4faa", - "reference": "a0a1690543329685c044362c873b78c6de9d4faa", + "url": "https://api.github.com/repos/symfony/cache/zipball/5b94fba945d1f9e7929cffd50e7a17f1ac36f10b", + "reference": "5b94fba945d1f9e7929cffd50e7a17f1ac36f10b", "shasum": "" }, "require": { @@ -1853,7 +1855,7 @@ "symfony/messenger": "^5.4|^6.0|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2026-02-20T15:06:30+00:00", + "time": "2026-03-30T14:52:43+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1888,7 +1890,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.34" + "source": "https://github.com/symfony/cache/tree/v6.4.36" }, "funding": [ { @@ -2073,17 +2075,17 @@ }, { "name": "symfony/console", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "7b1f1c37eff5910ddda2831345467e593a5120ad" + "reference": "9f481cfb580db8bcecc9b2d4c63f3e13df022ad5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/7b1f1c37eff5910ddda2831345467e593a5120ad", - "reference": "7b1f1c37eff5910ddda2831345467e593a5120ad", + "url": "https://api.github.com/repos/symfony/console/zipball/9f481cfb580db8bcecc9b2d4c63f3e13df022ad5", + "reference": "9f481cfb580db8bcecc9b2d4c63f3e13df022ad5", "shasum": "" }, "require": { @@ -2116,7 +2118,7 @@ "symfony/stopwatch": "^5.4|^6.0|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2026-02-23T15:42:15+00:00", + "time": "2026-03-27T15:30:51+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2150,7 +2152,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.34" + "source": "https://github.com/symfony/console/tree/v6.4.36" }, "funding": [ { @@ -2245,18 +2247,99 @@ "install-path": "../symfony/css-selector" }, { - "name": "symfony/dependency-injection", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "name": "symfony/debug-bundle", + "version": "v6.4.35", + "version_normalized": "6.4.35.0", "source": { "type": "git", - "url": "https://github.com/symfony/dependency-injection.git", - "reference": "91e49958b8a6092e48e4711894a1aeb1b151c62a" + "url": "https://github.com/symfony/debug-bundle.git", + "reference": "eb79084c2c9778559b21f61cb1507cbd580cc6e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/91e49958b8a6092e48e4711894a1aeb1b151c62a", - "reference": "91e49958b8a6092e48e4711894a1aeb1b151c62a", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/eb79084c2c9778559b21f61cb1507cbd580cc6e1", + "reference": "eb79084c2c9778559b21f61cb1507cbd580cc6e1", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": ">=8.1", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/twig-bridge": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4" + }, + "require-dev": { + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" + }, + "time": "2026-03-02T09:25:10+00:00", + "type": "symfony-bundle", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\DebugBundle\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "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.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/debug-bundle" + }, + { + "name": "symfony/dependency-injection", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dependency-injection.git", + "reference": "cd7881a6dc84b780411199cd0584e1a53a3b9ba7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/cd7881a6dc84b780411199cd0584e1a53a3b9ba7", + "reference": "cd7881a6dc84b780411199cd0584e1a53a3b9ba7", "shasum": "" }, "require": { @@ -2282,7 +2365,7 @@ "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2026-02-24T15:33:38+00:00", + "time": "2026-03-30T16:39:36+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2310,7 +2393,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.34" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.36" }, "funding": [ { @@ -2404,17 +2487,17 @@ }, { "name": "symfony/dotenv", - "version": "v6.4.30", - "version_normalized": "6.4.30.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "924edbc9631b75302def0258ed1697948b17baf6" + "reference": "cae019cc92a46fe9e498ea011107f26bdf5d897f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/924edbc9631b75302def0258ed1697948b17baf6", - "reference": "924edbc9631b75302def0258ed1697948b17baf6", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/cae019cc92a46fe9e498ea011107f26bdf5d897f", + "reference": "cae019cc92a46fe9e498ea011107f26bdf5d897f", "shasum": "" }, "require": { @@ -2428,7 +2511,7 @@ "symfony/console": "^5.4|^6.0|^7.0", "symfony/process": "^5.4|^6.0|^7.0" }, - "time": "2025-11-14T17:33:48+00:00", + "time": "2026-03-30T07:25:04+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2461,7 +2544,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.30" + "source": "https://github.com/symfony/dotenv/tree/v6.4.36" }, "funding": [ { @@ -2485,17 +2568,17 @@ }, { "name": "symfony/error-handler", - "version": "v6.4.32", - "version_normalized": "6.4.32.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8c18400784fcb014dc73c8d5601a9576af7f8ad4" + "reference": "2ea68f0e1835ad6a126f93bbc14cd236c10ab361" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8c18400784fcb014dc73c8d5601a9576af7f8ad4", - "reference": "8c18400784fcb014dc73c8d5601a9576af7f8ad4", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/2ea68f0e1835ad6a126f93bbc14cd236c10ab361", + "reference": "2ea68f0e1835ad6a126f93bbc14cd236c10ab361", "shasum": "" }, "require": { @@ -2512,7 +2595,7 @@ "symfony/http-kernel": "^6.4|^7.0", "symfony/serializer": "^5.4|^6.0|^7.0" }, - "time": "2026-01-19T19:28:19+00:00", + "time": "2026-03-10T15:56:14+00:00", "bin": [ "Resources/bin/patch-type-declarations" ], @@ -2543,7 +2626,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.32" + "source": "https://github.com/symfony/error-handler/tree/v6.4.36" }, "funding": [ { @@ -2567,17 +2650,17 @@ }, { "name": "symfony/event-dispatcher", - "version": "v6.4.32", - "version_normalized": "6.4.32.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "99d7e101826e6610606b9433248f80c1997cd20b" + "reference": "fc828863e26ceec86e2513b5e46aa0b149d76b69" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99d7e101826e6610606b9433248f80c1997cd20b", - "reference": "99d7e101826e6610606b9433248f80c1997cd20b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/fc828863e26ceec86e2513b5e46aa0b149d76b69", + "reference": "fc828863e26ceec86e2513b5e46aa0b149d76b69", "shasum": "" }, "require": { @@ -2602,7 +2685,7 @@ "symfony/service-contracts": "^2.5|^3", "symfony/stopwatch": "^5.4|^6.0|^7.0" }, - "time": "2026-01-05T11:13:48+00:00", + "time": "2026-03-30T11:18:01+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2630,7 +2713,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.32" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.36" }, "funding": [ { @@ -2877,17 +2960,17 @@ }, { "name": "symfony/form", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "ed9275a133809bb48d949ba6dfdc808a819ebea2" + "reference": "3a38a81150400f0a486f8963e21a195311b30b27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/ed9275a133809bb48d949ba6dfdc808a819ebea2", - "reference": "ed9275a133809bb48d949ba6dfdc808a819ebea2", + "url": "https://api.github.com/repos/symfony/form/zipball/3a38a81150400f0a486f8963e21a195311b30b27", + "reference": "3a38a81150400f0a486f8963e21a195311b30b27", "shasum": "" }, "require": { @@ -2929,7 +3012,7 @@ "symfony/validator": "^5.4|^6.0|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2026-02-23T17:59:52+00:00", + "time": "2026-03-13T14:59:02+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -2957,7 +3040,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v6.4.34" + "source": "https://github.com/symfony/form/tree/v6.4.36" }, "funding": [ { @@ -2981,17 +3064,17 @@ }, { "name": "symfony/framework-bundle", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "5b5d19473f22d699811a41b01cef2462bc42b238" + "reference": "147b02cfa45dcc74a290462551f5ee5c7fa8ab17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/5b5d19473f22d699811a41b01cef2462bc42b238", - "reference": "5b5d19473f22d699811a41b01cef2462bc42b238", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/147b02cfa45dcc74a290462551f5ee5c7fa8ab17", + "reference": "147b02cfa45dcc74a290462551f5ee5c7fa8ab17", "shasum": "" }, "require": { @@ -3085,7 +3168,7 @@ "symfony/yaml": "^5.4|^6.0|^7.0", "twig/twig": "^2.10|^3.0.4" }, - "time": "2026-02-24T16:00:52+00:00", + "time": "2026-03-25T17:41:29+00:00", "type": "symfony-bundle", "installation-source": "dist", "autoload": { @@ -3113,7 +3196,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.34" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.36" }, "funding": [ { @@ -3137,17 +3220,17 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.35", + "version_normalized": "6.4.35.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "5bb346d1b4b2a616e5c3d99b3ee4d5810735c535" + "reference": "cffffd0a2c037117b742b4f8b379a22a2a33f6d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5bb346d1b4b2a616e5c3d99b3ee4d5810735c535", - "reference": "5bb346d1b4b2a616e5c3d99b3ee4d5810735c535", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cffffd0a2c037117b742b4f8b379a22a2a33f6d2", + "reference": "cffffd0a2c037117b742b4f8b379a22a2a33f6d2", "shasum": "" }, "require": { @@ -3169,7 +3252,7 @@ "symfony/mime": "^5.4|^6.0|^7.0", "symfony/rate-limiter": "^5.4|^6.0|^7.0" }, - "time": "2026-02-21T15:48:41+00:00", + "time": "2026-03-06T11:15:58+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3197,7 +3280,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.34" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.35" }, "funding": [ { @@ -3221,17 +3304,17 @@ }, { "name": "symfony/http-kernel", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "006a49fc4f41ee21a6ca61e69caed1c30b29f07c" + "reference": "4087ec02119de450e9ebb60806d69c6bb8c6e468" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/006a49fc4f41ee21a6ca61e69caed1c30b29f07c", - "reference": "006a49fc4f41ee21a6ca61e69caed1c30b29f07c", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/4087ec02119de450e9ebb60806d69c6bb8c6e468", + "reference": "4087ec02119de450e9ebb60806d69c6bb8c6e468", "shasum": "" }, "require": { @@ -3290,7 +3373,7 @@ "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "time": "2026-02-26T08:27:11+00:00", + "time": "2026-03-31T20:38:11+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3318,7 +3401,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.34" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.36" }, "funding": [ { @@ -3429,17 +3512,17 @@ }, { "name": "symfony/mime", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "2b32fbbe10b36a8379efab6e702ad8b917151839" + "reference": "9c31726137c70798f815fb98293ffb8a2a47694c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/2b32fbbe10b36a8379efab6e702ad8b917151839", - "reference": "2b32fbbe10b36a8379efab6e702ad8b917151839", + "url": "https://api.github.com/repos/symfony/mime/zipball/9c31726137c70798f815fb98293ffb8a2a47694c", + "reference": "9c31726137c70798f815fb98293ffb8a2a47694c", "shasum": "" }, "require": { @@ -3465,7 +3548,7 @@ "symfony/property-info": "^5.4|^6.0|^7.0", "symfony/serializer": "^6.4.3|^7.0.3" }, - "time": "2026-02-02T17:01:23+00:00", + "time": "2026-03-30T09:31:23+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -3497,7 +3580,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.34" + "source": "https://github.com/symfony/mime/tree/v6.4.36" }, "funding": [ { @@ -3674,17 +3757,17 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.36.0", + "version_normalized": "1.36.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -3696,7 +3779,7 @@ "suggest": { "ext-ctype": "For best performance" }, - "time": "2024-09-09T11:45:10+00:00", + "time": "2026-04-10T16:19:22+00:00", "type": "library", "extra": { "thanks": { @@ -3736,7 +3819,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.36.0" }, "funding": [ { @@ -3760,17 +3843,17 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.36.0", + "version_normalized": "1.36.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/ad1b7b9092976d6c948b8a187cec9faaea9ec1df", + "reference": "ad1b7b9092976d6c948b8a187cec9faaea9ec1df", "shasum": "" }, "require": { @@ -3779,7 +3862,7 @@ "suggest": { "ext-intl": "For best performance" }, - "time": "2025-06-27T09:58:17+00:00", + "time": "2026-04-10T16:19:22+00:00", "type": "library", "extra": { "thanks": { @@ -3821,7 +3904,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.36.0" }, "funding": [ { @@ -3845,17 +3928,17 @@ }, { "name": "symfony/polyfill-intl-icu", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.36.0", + "version_normalized": "1.36.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-icu.git", - "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c" + "reference": "3510b63d07376b04e57e27e82607d468bb134f78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c", - "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/3510b63d07376b04e57e27e82607d468bb134f78", + "reference": "3510b63d07376b04e57e27e82607d468bb134f78", "shasum": "" }, "require": { @@ -3864,7 +3947,7 @@ "suggest": { "ext-intl": "For best performance and support of other locales than \"en\"" }, - "time": "2025-06-20T22:24:30+00:00", + "time": "2026-04-10T16:50:15+00:00", "type": "library", "extra": { "thanks": { @@ -3912,7 +3995,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.36.0" }, "funding": [ { @@ -3936,8 +4019,8 @@ }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.36.0", + "version_normalized": "1.36.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -4002,7 +4085,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.36.0" }, "funding": [ { @@ -4026,8 +4109,8 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.36.0", + "version_normalized": "1.36.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -4090,7 +4173,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.36.0" }, "funding": [ { @@ -4114,17 +4197,17 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.36.0", + "version_normalized": "1.36.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315", + "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315", "shasum": "" }, "require": { @@ -4137,7 +4220,7 @@ "suggest": { "ext-mbstring": "For best performance" }, - "time": "2024-12-23T08:48:59+00:00", + "time": "2026-04-10T17:25:58+00:00", "type": "library", "extra": { "thanks": { @@ -4178,7 +4261,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.36.0" }, "funding": [ { @@ -4202,23 +4285,23 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.33.0", - "version_normalized": "1.33.0.0", + "version": "v1.36.0", + "version_normalized": "1.36.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/3600c2cb22399e25bb226e4a135ce91eeb2a6149", + "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149", "shasum": "" }, "require": { "php": ">=7.2" }, - "time": "2025-07-08T02:45:35+00:00", + "time": "2026-04-10T17:25:58+00:00", "type": "library", "extra": { "thanks": { @@ -4261,7 +4344,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.36.0" }, "funding": [ { @@ -4551,18 +4634,104 @@ "install-path": "../symfony/routing" }, { - "name": "symfony/security-core", - "version": "v6.4.31", - "version_normalized": "6.4.31.0", + "name": "symfony/runtime", + "version": "v6.4.30", + "version_normalized": "6.4.30.0", "source": { "type": "git", - "url": "https://github.com/symfony/security-core.git", - "reference": "fa269ad61a021cc54329dc96e57bed78ba720bfe" + "url": "https://github.com/symfony/runtime.git", + "reference": "fb3149ee85d3b639dd3e49ea9dda05656f0537e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/fa269ad61a021cc54329dc96e57bed78ba720bfe", - "reference": "fa269ad61a021cc54329dc96e57bed78ba720bfe", + "url": "https://api.github.com/repos/symfony/runtime/zipball/fb3149ee85d3b639dd3e49ea9dda05656f0537e3", + "reference": "fb3149ee85d3b639dd3e49ea9dda05656f0537e3", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": ">=8.1" + }, + "conflict": { + "symfony/dotenv": "<5.4" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "symfony/console": "^5.4.9|^6.0.9|^7.0", + "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0" + }, + "time": "2025-12-05T10:55:13+00:00", + "type": "composer-plugin", + "extra": { + "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Runtime\\": "", + "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "Enables decoupling PHP applications from global state", + "homepage": "https://symfony.com", + "keywords": [ + "runtime" + ], + "support": { + "source": "https://github.com/symfony/runtime/tree/v6.4.30" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "install-path": "../symfony/runtime" + }, + { + "name": "symfony/security-core", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/security-core.git", + "reference": "1b7db28bcc3655543abfe58764025aef563705cd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/security-core/zipball/1b7db28bcc3655543abfe58764025aef563705cd", + "reference": "1b7db28bcc3655543abfe58764025aef563705cd", "shasum": "" }, "require": { @@ -4593,7 +4762,7 @@ "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", "symfony/validator": "^6.4|^7.0" }, - "time": "2025-12-17T22:32:13+00:00", + "time": "2026-03-31T01:40:43+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4621,7 +4790,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.4.31" + "source": "https://github.com/symfony/security-core/tree/v6.4.36" }, "funding": [ { @@ -5056,17 +5225,17 @@ }, { "name": "symfony/twig-bridge", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "5169074f4a88dfb02eeccddaba78edfdf212a9b2" + "reference": "3ae963a108fd6fc14d09a7fe5e41fe64d8ac11ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/5169074f4a88dfb02eeccddaba78edfdf212a9b2", - "reference": "5169074f4a88dfb02eeccddaba78edfdf212a9b2", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/3ae963a108fd6fc14d09a7fe5e41fe64d8ac11ba", + "reference": "3ae963a108fd6fc14d09a7fe5e41fe64d8ac11ba", "shasum": "" }, "require": { @@ -5120,7 +5289,7 @@ "twig/inky-extra": "^2.12|^3", "twig/markdown-extra": "^2.12|^3" }, - "time": "2026-02-23T18:17:33+00:00", + "time": "2026-03-30T09:31:23+00:00", "type": "symfony-bridge", "installation-source": "dist", "autoload": { @@ -5148,7 +5317,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.34" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.36" }, "funding": [ { @@ -5263,17 +5432,17 @@ }, { "name": "symfony/validator", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "7c3897b7f739d4ab913481e680405ca82d08084d" + "reference": "14921e87b2bd69dfbd9757cdb1c6974a1316aac5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/7c3897b7f739d4ab913481e680405ca82d08084d", - "reference": "7c3897b7f739d4ab913481e680405ca82d08084d", + "url": "https://api.github.com/repos/symfony/validator/zipball/14921e87b2bd69dfbd9757cdb1c6974a1316aac5", + "reference": "14921e87b2bd69dfbd9757cdb1c6974a1316aac5", "shasum": "" }, "require": { @@ -5314,7 +5483,7 @@ "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", "symfony/yaml": "^5.4|^6.0|^7.0" }, - "time": "2026-02-23T17:49:24+00:00", + "time": "2026-03-26T15:58:46+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -5343,7 +5512,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.34" + "source": "https://github.com/symfony/validator/tree/v6.4.36" }, "funding": [ { @@ -5367,17 +5536,17 @@ }, { "name": "symfony/var-dumper", - "version": "v6.4.32", - "version_normalized": "6.4.32.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "131fc9915e0343052af5ed5040401b481ca192aa" + "reference": "7c8ad9ce4faf6c8a99948e70ce02b601a0439782" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/131fc9915e0343052af5ed5040401b481ca192aa", - "reference": "131fc9915e0343052af5ed5040401b481ca192aa", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7c8ad9ce4faf6c8a99948e70ce02b601a0439782", + "reference": "7c8ad9ce4faf6c8a99948e70ce02b601a0439782", "shasum": "" }, "require": { @@ -5396,7 +5565,7 @@ "symfony/uid": "^5.4|^6.0|^7.0", "twig/twig": "^2.13|^3.0.4" }, - "time": "2026-01-01T13:34:06+00:00", + "time": "2026-03-30T15:36:00+00:00", "bin": [ "Resources/bin/var-dump-server" ], @@ -5434,7 +5603,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.32" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.36" }, "funding": [ { @@ -5458,17 +5627,17 @@ }, { "name": "symfony/var-exporter", - "version": "v6.4.26", - "version_normalized": "6.4.26.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc" + "reference": "f9c4a9695a9e2bbc65c920e147d8d7ae28f8d79a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/466fcac5fa2e871f83d31173f80e9c2684743bfc", - "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f9c4a9695a9e2bbc65c920e147d8d7ae28f8d79a", + "reference": "f9c4a9695a9e2bbc65c920e147d8d7ae28f8d79a", "shasum": "" }, "require": { @@ -5480,7 +5649,7 @@ "symfony/serializer": "^6.4|^7.0", "symfony/var-dumper": "^5.4|^6.0|^7.0" }, - "time": "2025-09-11T09:57:09+00:00", + "time": "2026-03-10T15:06:19+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -5518,7 +5687,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.26" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.36" }, "funding": [ { @@ -5542,17 +5711,17 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.34", - "version_normalized": "6.4.34.0", + "version": "v6.4.36", + "version_normalized": "6.4.36.0", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "848bc5d5745500f855bb201d57ae066fd7e67448" + "reference": "6f75b4c748886c8e04a3674225d00eaa51f3842d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/848bc5d5745500f855bb201d57ae066fd7e67448", - "reference": "848bc5d5745500f855bb201d57ae066fd7e67448", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/6f75b4c748886c8e04a3674225d00eaa51f3842d", + "reference": "6f75b4c748886c8e04a3674225d00eaa51f3842d", "shasum": "" }, "require": { @@ -5576,7 +5745,7 @@ "symfony/css-selector": "^5.4|^6.0|^7.0", "symfony/stopwatch": "^5.4|^6.0|^7.0" }, - "time": "2026-02-05T15:19:06+00:00", + "time": "2026-03-17T09:05:06+00:00", "type": "symfony-bundle", "installation-source": "dist", "autoload": { @@ -5607,7 +5776,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.34" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.36" }, "funding": [ { @@ -5710,24 +5879,24 @@ }, { "name": "tecnickcom/tcpdf", - "version": "6.11.0", - "version_normalized": "6.11.0.0", + "version": "6.11.2", + "version_normalized": "6.11.2.0", "source": { "type": "git", "url": "https://github.com/tecnickcom/TCPDF.git", - "reference": "81172e58edb1cfae4019ef150ccbdc0e9a8c85c9" + "reference": "e1e2ade18e574e963473f53271591edd8c0033ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/81172e58edb1cfae4019ef150ccbdc0e9a8c85c9", - "reference": "81172e58edb1cfae4019ef150ccbdc0e9a8c85c9", + "url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/e1e2ade18e574e963473f53271591edd8c0033ec", + "reference": "e1e2ade18e574e963473f53271591edd8c0033ec", "shasum": "" }, "require": { "ext-curl": "*", "php": ">=7.1.0" }, - "time": "2026-03-01T09:35:25+00:00", + "time": "2026-03-03T08:58:10+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -5772,7 +5941,7 @@ ], "support": { "issues": "https://github.com/tecnickcom/TCPDF/issues", - "source": "https://github.com/tecnickcom/TCPDF/tree/6.11.0" + "source": "https://github.com/tecnickcom/TCPDF/tree/6.11.2" }, "funding": [ { @@ -5847,17 +6016,17 @@ }, { "name": "twig/twig", - "version": "v3.23.0", - "version_normalized": "3.23.0.0", + "version": "v3.24.0", + "version_normalized": "3.24.0.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9" + "reference": "a6769aefb305efef849dc25c9fd1653358c148f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", - "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a6769aefb305efef849dc25c9fd1653358c148f0", + "reference": "a6769aefb305efef849dc25c9fd1653358c148f0", "shasum": "" }, "require": { @@ -5867,11 +6036,12 @@ "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { - "phpstan/phpstan": "^2.0", + "php-cs-fixer/shim": "^3.0@stable", + "phpstan/phpstan": "^2.0@stable", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, - "time": "2026-01-23T21:00:41+00:00", + "time": "2026-03-17T21:31:11+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -5913,7 +6083,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.23.0" + "source": "https://github.com/twigphp/Twig/tree/v3.24.0" }, "funding": [ { @@ -5930,6 +6100,7 @@ ], "dev": true, "dev-package-names": [ + "symfony/debug-bundle", "symfony/stopwatch", "symfony/web-profiler-bundle" ] diff --git a/lib/composer/installed.php b/lib/composer/installed.php index 1504d6c66..11d4ff1ca 100644 --- a/lib/composer/installed.php +++ b/lib/composer/installed.php @@ -1,9 +1,9 @@ array( 'name' => 'combodo/itop', - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => null, + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => '3ccbfb2b130419fec9d1158836395a13baa0ec4b', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -22,9 +22,9 @@ 'dev_requirement' => false, ), 'combodo/itop' => array( - 'pretty_version' => '1.0.0+no-version-set', - 'version' => '1.0.0.0', - 'reference' => null, + 'pretty_version' => 'dev-develop', + 'version' => 'dev-develop', + 'reference' => '3ccbfb2b130419fec9d1158836395a13baa0ec4b', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -49,9 +49,9 @@ 'dev_requirement' => false, ), 'firebase/php-jwt' => array( - 'pretty_version' => 'v7.0.3', - 'version' => '7.0.3.0', - 'reference' => '28aa0694bcfdfa5e2959c394d5a1ee7a5083629e', + 'pretty_version' => 'v7.0.5', + 'version' => '7.0.5.0', + 'reference' => '47ad26bab5e7c70ae8a6f08ed25ff83631121380', 'type' => 'library', 'install_path' => __DIR__ . '/../firebase/php-jwt', 'aliases' => array(), @@ -76,9 +76,9 @@ 'dev_requirement' => false, ), 'guzzlehttp/psr7' => array( - 'pretty_version' => '2.8.0', - 'version' => '2.8.0.0', - 'reference' => '21dc724a0583619cd1652f673303492272778051', + 'pretty_version' => '2.9.0', + 'version' => '2.9.0.0', + 'reference' => '7d0ed42f28e42d61352a7a79de682e5e67fec884', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/psr7', 'aliases' => array(), @@ -94,9 +94,9 @@ 'dev_requirement' => false, ), 'league/oauth2-google' => array( - 'pretty_version' => '4.1.0', - 'version' => '4.1.0.0', - 'reference' => '8b9bb43740ac6d994aca881a35f7bacbe98c0ffb', + 'pretty_version' => '4.2.0', + 'version' => '4.2.0.0', + 'reference' => '72be69505f890ea8b6d4e716f619b3c10a1f5010', 'type' => 'library', 'install_path' => __DIR__ . '/../league/oauth2-google', 'aliases' => array(), @@ -105,7 +105,7 @@ 'nikic/php-parser' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => 'b2cd0735eb27788d5d41fa3c2cfaa01a593fd7fb', + 'reference' => 'b27e577f70d2114b8ba96105e403017919a8611b', 'type' => 'library', 'install_path' => __DIR__ . '/../nikic/php-parser', 'aliases' => array( @@ -312,9 +312,9 @@ 'dev_requirement' => false, ), 'symfony/cache' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => 'a0a1690543329685c044362c873b78c6de9d4faa', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '5b94fba945d1f9e7929cffd50e7a17f1ac36f10b', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/cache', 'aliases' => array(), @@ -345,9 +345,9 @@ 'dev_requirement' => false, ), 'symfony/console' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '7b1f1c37eff5910ddda2831345467e593a5120ad', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '9f481cfb580db8bcecc9b2d4c63f3e13df022ad5', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), @@ -362,10 +362,19 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/debug-bundle' => array( + 'pretty_version' => 'v6.4.35', + 'version' => '6.4.35.0', + 'reference' => 'eb79084c2c9778559b21f61cb1507cbd580cc6e1', + 'type' => 'symfony-bundle', + 'install_path' => __DIR__ . '/../symfony/debug-bundle', + 'aliases' => array(), + 'dev_requirement' => true, + ), 'symfony/dependency-injection' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '91e49958b8a6092e48e4711894a1aeb1b151c62a', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => 'cd7881a6dc84b780411199cd0584e1a53a3b9ba7', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dependency-injection', 'aliases' => array(), @@ -381,27 +390,27 @@ 'dev_requirement' => false, ), 'symfony/dotenv' => array( - 'pretty_version' => 'v6.4.30', - 'version' => '6.4.30.0', - 'reference' => '924edbc9631b75302def0258ed1697948b17baf6', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => 'cae019cc92a46fe9e498ea011107f26bdf5d897f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dotenv', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/error-handler' => array( - 'pretty_version' => 'v6.4.32', - 'version' => '6.4.32.0', - 'reference' => '8c18400784fcb014dc73c8d5601a9576af7f8ad4', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '2ea68f0e1835ad6a126f93bbc14cd236c10ab361', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/error-handler', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/event-dispatcher' => array( - 'pretty_version' => 'v6.4.32', - 'version' => '6.4.32.0', - 'reference' => '99d7e101826e6610606b9433248f80c1997cd20b', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => 'fc828863e26ceec86e2513b5e46aa0b149d76b69', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'aliases' => array(), @@ -441,36 +450,36 @@ 'dev_requirement' => false, ), 'symfony/form' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => 'ed9275a133809bb48d949ba6dfdc808a819ebea2', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '3a38a81150400f0a486f8963e21a195311b30b27', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/form', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/framework-bundle' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '5b5d19473f22d699811a41b01cef2462bc42b238', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '147b02cfa45dcc74a290462551f5ee5c7fa8ab17', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/framework-bundle', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-foundation' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '5bb346d1b4b2a616e5c3d99b3ee4d5810735c535', + 'pretty_version' => 'v6.4.35', + 'version' => '6.4.35.0', + 'reference' => 'cffffd0a2c037117b742b4f8b379a22a2a33f6d2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/http-kernel' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '006a49fc4f41ee21a6ca61e69caed1c30b29f07c', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '4087ec02119de450e9ebb60806d69c6bb8c6e468', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-kernel', 'aliases' => array(), @@ -486,9 +495,9 @@ 'dev_requirement' => false, ), 'symfony/mime' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '2b32fbbe10b36a8379efab6e702ad8b917151839', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '9c31726137c70798f815fb98293ffb8a2a47694c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/mime', 'aliases' => array(), @@ -513,35 +522,35 @@ 'dev_requirement' => false, ), 'symfony/polyfill-ctype' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', - 'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638', + 'pretty_version' => 'v1.36.0', + 'version' => '1.36.0.0', + 'reference' => '141046a8f9477948ff284fa65be2095baafb94f2', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-grapheme' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', - 'reference' => '380872130d3a5dd3ace2f4010d95125fde5d5c70', + 'pretty_version' => 'v1.36.0', + 'version' => '1.36.0.0', + 'reference' => 'ad1b7b9092976d6c948b8a187cec9faaea9ec1df', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-icu' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', - 'reference' => 'bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c', + 'pretty_version' => 'v1.36.0', + 'version' => '1.36.0.0', + 'reference' => '3510b63d07376b04e57e27e82607d468bb134f78', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-icu', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-intl-idn' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', + 'pretty_version' => 'v1.36.0', + 'version' => '1.36.0.0', 'reference' => '9614ac4d8061dc257ecc64cba1b140873dce8ad3', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn', @@ -549,8 +558,8 @@ 'dev_requirement' => false, ), 'symfony/polyfill-intl-normalizer' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', + 'pretty_version' => 'v1.36.0', + 'version' => '1.36.0.0', 'reference' => '3833d7255cc303546435cb650316bff708a1c75c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', @@ -558,18 +567,18 @@ 'dev_requirement' => false, ), 'symfony/polyfill-mbstring' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', - 'reference' => '6d857f4d76bd4b343eac26d6b539585d2bc56493', + 'pretty_version' => 'v1.36.0', + 'version' => '1.36.0.0', + 'reference' => '6a21eb99c6973357967f6ce3708cd55a6bec6315', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/polyfill-php83' => array( - 'pretty_version' => 'v1.33.0', - 'version' => '1.33.0.0', - 'reference' => '17f6f9a6b1735c0f163024d959f700cfbc5155e5', + 'pretty_version' => 'v1.36.0', + 'version' => '1.36.0.0', + 'reference' => '3600c2cb22399e25bb226e4a135ce91eeb2a6149', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php83', 'aliases' => array(), @@ -602,10 +611,19 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'symfony/runtime' => array( + 'pretty_version' => 'v6.4.30', + 'version' => '6.4.30.0', + 'reference' => 'fb3149ee85d3b639dd3e49ea9dda05656f0537e3', + 'type' => 'composer-plugin', + 'install_path' => __DIR__ . '/../symfony/runtime', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'symfony/security-core' => array( - 'pretty_version' => 'v6.4.31', - 'version' => '6.4.31.0', - 'reference' => 'fa269ad61a021cc54329dc96e57bed78ba720bfe', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '1b7db28bcc3655543abfe58764025aef563705cd', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/security-core', 'aliases' => array(), @@ -663,9 +681,9 @@ 'dev_requirement' => false, ), 'symfony/twig-bridge' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '5169074f4a88dfb02eeccddaba78edfdf212a9b2', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '3ae963a108fd6fc14d09a7fe5e41fe64d8ac11ba', 'type' => 'symfony-bridge', 'install_path' => __DIR__ . '/../symfony/twig-bridge', 'aliases' => array(), @@ -681,36 +699,36 @@ 'dev_requirement' => false, ), 'symfony/validator' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '7c3897b7f739d4ab913481e680405ca82d08084d', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '14921e87b2bd69dfbd9757cdb1c6974a1316aac5', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/validator', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/var-dumper' => array( - 'pretty_version' => 'v6.4.32', - 'version' => '6.4.32.0', - 'reference' => '131fc9915e0343052af5ed5040401b481ca192aa', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '7c8ad9ce4faf6c8a99948e70ce02b601a0439782', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/var-exporter' => array( - 'pretty_version' => 'v6.4.26', - 'version' => '6.4.26.0', - 'reference' => '466fcac5fa2e871f83d31173f80e9c2684743bfc', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => 'f9c4a9695a9e2bbc65c920e147d8d7ae28f8d79a', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-exporter', 'aliases' => array(), 'dev_requirement' => false, ), 'symfony/web-profiler-bundle' => array( - 'pretty_version' => 'v6.4.34', - 'version' => '6.4.34.0', - 'reference' => '848bc5d5745500f855bb201d57ae066fd7e67448', + 'pretty_version' => 'v6.4.36', + 'version' => '6.4.36.0', + 'reference' => '6f75b4c748886c8e04a3674225d00eaa51f3842d', 'type' => 'symfony-bundle', 'install_path' => __DIR__ . '/../symfony/web-profiler-bundle', 'aliases' => array(), @@ -726,9 +744,9 @@ 'dev_requirement' => false, ), 'tecnickcom/tcpdf' => array( - 'pretty_version' => '6.11.0', - 'version' => '6.11.0.0', - 'reference' => '81172e58edb1cfae4019ef150ccbdc0e9a8c85c9', + 'pretty_version' => '6.11.2', + 'version' => '6.11.2.0', + 'reference' => 'e1e2ade18e574e963473f53271591edd8c0033ec', 'type' => 'library', 'install_path' => __DIR__ . '/../tecnickcom/tcpdf', 'aliases' => array(), @@ -744,9 +762,9 @@ 'dev_requirement' => false, ), 'twig/twig' => array( - 'pretty_version' => 'v3.23.0', - 'version' => '3.23.0.0', - 'reference' => 'a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9', + 'pretty_version' => 'v3.24.0', + 'version' => '3.24.0.0', + 'reference' => 'a6769aefb305efef849dc25c9fd1653358c148f0', 'type' => 'library', 'install_path' => __DIR__ . '/../twig/twig', 'aliases' => array(), diff --git a/lib/composer/platform_check.php b/lib/composer/platform_check.php index 72145773d..f6cf0ea27 100644 --- a/lib/composer/platform_check.php +++ b/lib/composer/platform_check.php @@ -4,8 +4,8 @@ $issues = array(); -if (!(PHP_VERSION_ID >= 80100)) { - $issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.'; +if (!(PHP_VERSION_ID >= 80200)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.'; } $missingExtensions = array(); diff --git a/lib/firebase/php-jwt/CHANGELOG.md b/lib/firebase/php-jwt/CHANGELOG.md index 32a5433ac..498fb0007 100644 --- a/lib/firebase/php-jwt/CHANGELOG.md +++ b/lib/firebase/php-jwt/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [7.0.5](https://github.com/firebase/php-jwt/compare/v7.0.4...v7.0.5) (2026-03-31) + + +### Bug Fixes + +* RSA from JWK sometimes returns empty Instance ([#628](https://github.com/firebase/php-jwt/issues/628)) ([b4c78aa](https://github.com/firebase/php-jwt/commit/b4c78aa731664122198ad36c0033aa29e807397a)) + +## [7.0.4](https://github.com/firebase/php-jwt/compare/v7.0.3...v7.0.4) (2026-03-27) + + +### Bug Fixes + +* readme examples, add tests for all examples ([#626](https://github.com/firebase/php-jwt/issues/626)) ([510a00c](https://github.com/firebase/php-jwt/commit/510a00c0e6353bc7d68412fab67e57a13954cb46)) +* use urlsafeB64Decode everywhere ([#627](https://github.com/firebase/php-jwt/issues/627)) ([b889495](https://github.com/firebase/php-jwt/commit/b889495c83ddc3f3885ca3f0b65b41b1cb37a3b1)) + ## [7.0.3](https://github.com/firebase/php-jwt/compare/v7.0.2...v7.0.3) (2026-02-18) diff --git a/lib/firebase/php-jwt/README.md b/lib/firebase/php-jwt/README.md index 65b6c8609..2ca716224 100644 --- a/lib/firebase/php-jwt/README.md +++ b/lib/firebase/php-jwt/README.md @@ -23,16 +23,16 @@ php env does not have libsodium installed: composer require paragonie/sodium_compat ``` -Example -------- +## Example + ```php use Firebase\JWT\JWT; use Firebase\JWT\Key; -$key = 'example_key'; +$key = 'example_key_of_sufficient_length'; $payload = [ - 'iss' => 'http://example.org', - 'aud' => 'http://example.com', + 'iss' => 'example.org', + 'aud' => 'example.com', 'iat' => 1356999524, 'nbf' => 1357000000 ]; @@ -69,8 +69,9 @@ $decoded_array = (array) $decoded; JWT::$leeway = 60; // $leeway in seconds $decoded = JWT::decode($jwt, new Key($key, 'HS256')); ``` -Example encode/decode headers -------- + +## Example encode/decode headers + Decoding the JWT headers without verifying the JWT first is NOT recommended, and is not supported by this library. This is because without verifying the JWT, the header values could have been tampered with. Any value pulled from an unverified header should be treated as if it could be any string sent in from an @@ -80,10 +81,10 @@ header part: ```php use Firebase\JWT\JWT; -$key = 'example_key'; +$key = 'example_key_of_sufficient_length'; $payload = [ - 'iss' => 'http://example.org', - 'aud' => 'http://example.com', + 'iss' => 'example.org', + 'aud' => 'example.com', 'iat' => 1356999524, 'nbf' => 1357000000 ]; @@ -103,8 +104,9 @@ $decoded = json_decode(base64_decode($headersB64), true); print_r($decoded); ``` -Example with RS256 (openssl) ----------------------------- + +## Example with RS256 (openssl) + ```php use Firebase\JWT\JWT; use Firebase\JWT\Key; @@ -172,8 +174,7 @@ $decoded_array = (array) $decoded; echo "Decode:\n" . print_r($decoded_array, true) . "\n"; ``` -Example with a passphrase -------------------------- +## Example with a passphrase ```php use Firebase\JWT\JWT; @@ -209,8 +210,8 @@ $decoded = JWT::decode($jwt, new Key($publicKey, 'RS256')); echo "Decode:\n" . print_r((array) $decoded, true) . "\n"; ``` -Example with EdDSA (libsodium and Ed25519 signature) ----------------------------- +## Example with EdDSA (libsodium and Ed25519 signature) + ```php use Firebase\JWT\JWT; use Firebase\JWT\Key; @@ -238,21 +239,21 @@ echo "Encode:\n" . print_r($jwt, true) . "\n"; $decoded = JWT::decode($jwt, new Key($publicKey, 'EdDSA')); echo "Decode:\n" . print_r((array) $decoded, true) . "\n"; -```` +``` + +## Example with multiple keys -Example with multiple keys --------------------------- ```php use Firebase\JWT\JWT; use Firebase\JWT\Key; // Example RSA keys from previous example -// $privateKey1 = '...'; -// $publicKey1 = '...'; +// $privateRsKey = '...'; +// $publicRsKey = '...'; // Example EdDSA keys from previous example -// $privateKey2 = '...'; -// $publicKey2 = '...'; +// $privateEcKey = '...'; +// $publicEcKey = '...'; $payload = [ 'iss' => 'example.org', @@ -261,14 +262,14 @@ $payload = [ 'nbf' => 1357000000 ]; -$jwt1 = JWT::encode($payload, $privateKey1, 'RS256', 'kid1'); -$jwt2 = JWT::encode($payload, $privateKey2, 'EdDSA', 'kid2'); +$jwt1 = JWT::encode($payload, $privateRsKey, 'RS256', 'kid1'); +$jwt2 = JWT::encode($payload, $privateEcKey, 'EdDSA', 'kid2'); echo "Encode 1:\n" . print_r($jwt1, true) . "\n"; echo "Encode 2:\n" . print_r($jwt2, true) . "\n"; $keys = [ - 'kid1' => new Key($publicKey1, 'RS256'), - 'kid2' => new Key($publicKey2, 'EdDSA'), + 'kid1' => new Key($publicRsKey, 'RS256'), + 'kid2' => new Key($publicEcKey, 'EdDSA'), ]; $decoded1 = JWT::decode($jwt1, $keys); @@ -278,8 +279,7 @@ echo "Decode 1:\n" . print_r((array) $decoded1, true) . "\n"; echo "Decode 2:\n" . print_r((array) $decoded2, true) . "\n"; ``` -Using JWKs ----------- +## Using JWKs ```php use Firebase\JWT\JWK; @@ -291,11 +291,11 @@ $jwks = ['keys' => []]; // JWK::parseKeySet($jwks) returns an associative array of **kid** to Firebase\JWT\Key // objects. Pass this as the second parameter to JWT::decode. -JWT::decode($jwt, JWK::parseKeySet($jwks)); +$decoded = JWT::decode($jwt, JWK::parseKeySet($jwks)); +print_r($decoded); ``` -Using Cached Key Sets ---------------------- +## Using Cached Key Sets The `CachedKeySet` class can be used to fetch and cache JWKS (JSON Web Key Sets) from a public URI. This has the following advantages: @@ -315,7 +315,7 @@ $jwksUri = 'https://www.gstatic.com/iap/verify/public_key-jwk'; $httpClient = new GuzzleHttp\Client(); // Create an HTTP request factory (can be any PSR-17 compatible HTTP request factory) -$httpFactory = new GuzzleHttp\Psr\HttpFactory(); +$httpFactory = new GuzzleHttp\Psr7\HttpFactory(); // Create a cache item pool (can be any PSR-6 compatible cache item pool) $cacheItemPool = Phpfastcache\CacheManager::getInstance('files'); @@ -406,8 +406,8 @@ Tests Run the tests using phpunit: ```bash -$ pear install PHPUnit -$ phpunit --configuration phpunit.xml.dist +$ composer update +$ vendor/bin/phpunit -c phpunit.xml.dist PHPUnit 3.7.10 by Sebastian Bergmann. ..... Time: 0 seconds, Memory: 2.50Mb diff --git a/lib/firebase/php-jwt/composer.json b/lib/firebase/php-jwt/composer.json index 816cfd0bd..4b988631d 100644 --- a/lib/firebase/php-jwt/composer.json +++ b/lib/firebase/php-jwt/composer.json @@ -37,6 +37,7 @@ "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", "psr/http-client": "^1.0", - "psr/http-factory": "^1.0" + "psr/http-factory": "^1.0", + "phpfastcache/phpfastcache": "^9.2" } } diff --git a/lib/firebase/php-jwt/src/CachedKeySet.php b/lib/firebase/php-jwt/src/CachedKeySet.php index 8e8e8d68c..37c3f94d2 100644 --- a/lib/firebase/php-jwt/src/CachedKeySet.php +++ b/lib/firebase/php-jwt/src/CachedKeySet.php @@ -180,7 +180,8 @@ class CachedKeySet implements ArrayAccess $jwksResponse = $this->httpClient->sendRequest($request); if ($jwksResponse->getStatusCode() !== 200) { throw new UnexpectedValueException( - \sprintf('HTTP Error: %d %s for URI "%s"', + \sprintf( + 'HTTP Error: %d %s for URI "%s"', $jwksResponse->getStatusCode(), $jwksResponse->getReasonPhrase(), $this->jwksUri, diff --git a/lib/firebase/php-jwt/src/JWK.php b/lib/firebase/php-jwt/src/JWK.php index d5175b217..e083c224b 100644 --- a/lib/firebase/php-jwt/src/JWK.php +++ b/lib/firebase/php-jwt/src/JWK.php @@ -240,6 +240,14 @@ class JWK ): string { $mod = JWT::urlsafeB64Decode($n); $exp = JWT::urlsafeB64Decode($e); + // Correct encoding for ASN1, as ints are represented as unsigned in jwk + // but signed in ASN1. Prepending null byte makes it unsigned. + if (\strlen($mod) > 0 && \ord($mod[0]) >= 128) { + $mod = \chr(0) . $mod; + } + if (\strlen($exp) > 0 && \ord($exp[0]) >= 128) { + $exp = \chr(0) . $exp; + } $modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod); $publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp); diff --git a/lib/firebase/php-jwt/src/JWT.php b/lib/firebase/php-jwt/src/JWT.php index 90f62ca9d..0d2e47c95 100644 --- a/lib/firebase/php-jwt/src/JWT.php +++ b/lib/firebase/php-jwt/src/JWT.php @@ -31,7 +31,7 @@ class JWT private const ASN1_SEQUENCE = 0x10; private const ASN1_BIT_STRING = 0x03; - private const RSA_KEY_MIN_LENGTH=2048; + private const RSA_KEY_MIN_LENGTH = 2048; /** * When checking nbf, iat or expiration times, @@ -284,20 +284,8 @@ class JWT } return $signature; case 'sodium_crypto': - if (!\function_exists('sodium_crypto_sign_detached')) { - throw new DomainException('libsodium is not available'); - } - if (!\is_string($key)) { - throw new InvalidArgumentException('key must be a string when using EdDSA'); - } try { - // The last non-empty line is used as the key. - $lines = array_filter(explode("\n", $key)); - $key = base64_decode((string) end($lines)); - if (\strlen($key) === 0) { - throw new DomainException('Key cannot be empty string'); - } - return sodium_crypto_sign_detached($msg, $key); + return sodium_crypto_sign_detached($msg, self::validateEdDSAKey($key)); } catch (Exception $e) { throw new DomainException($e->getMessage(), 0, $e); } @@ -352,19 +340,8 @@ class JWT 'OpenSSL error: ' . \openssl_error_string() ); case 'sodium_crypto': - if (!\function_exists('sodium_crypto_sign_verify_detached')) { - throw new DomainException('libsodium is not available'); - } - if (!\is_string($keyMaterial)) { - throw new InvalidArgumentException('key must be a string when using EdDSA'); - } try { - // The last non-empty line is used as the key. - $lines = array_filter(explode("\n", $keyMaterial)); - $key = base64_decode((string) end($lines)); - if (\strlen($key) === 0) { - throw new DomainException('Key cannot be empty string'); - } + $key = self::validateEdDSAKey($keyMaterial); if (\strlen($signature) === 0) { throw new DomainException('Signature cannot be empty string'); } @@ -473,7 +450,6 @@ class JWT return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_')); } - /** * Determine if an algorithm has been provided for each Key * @@ -745,4 +721,25 @@ class JWT throw new DomainException('Provided key is too short'); } } + + /** + * @param string|OpenSSLAsymmetricKey|OpenSSLCertificate $keyMaterial + * @return non-empty-string + */ + private static function validateEdDSAKey(#[\SensitiveParameter] $keyMaterial): string + { + if (!\function_exists('sodium_crypto_sign_verify_detached')) { + throw new DomainException('libsodium is not available'); + } + if (!\is_string($keyMaterial)) { + throw new InvalidArgumentException('key must be a string when using EdDSA'); + } + // The last non-empty line is used as the key. + $lines = array_filter(explode("\n", $keyMaterial)); + $key = self::urlsafeB64Decode((string) end($lines)); + if (\strlen($key) === 0) { + throw new DomainException('Key cannot be empty string'); + } + return $key; + } } diff --git a/lib/guzzlehttp/psr7/CHANGELOG.md b/lib/guzzlehttp/psr7/CHANGELOG.md index 4a2a12194..6aca386e3 100644 --- a/lib/guzzlehttp/psr7/CHANGELOG.md +++ b/lib/guzzlehttp/psr7/CHANGELOG.md @@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 2.9.0 - 2026-03-10 + +### Added + +- Added nested array expansion support to `MultipartStream` +- Added `@return static` to `MessageTrait` methods + +### Changed + +- Updated MIME type mappings + +## 2.8.1 - 2026-03-10 + +### Fixed + +- Encode `+` signs in `Uri::withQueryValue()` and `Uri::withQueryValues()` to prevent them being interpreted as spaces + ## 2.8.0 - 2025-08-23 ### Added diff --git a/lib/guzzlehttp/psr7/composer.json b/lib/guzzlehttp/psr7/composer.json index 96098f536..56a320b9a 100644 --- a/lib/guzzlehttp/psr7/composer.json +++ b/lib/guzzlehttp/psr7/composer.json @@ -49,6 +49,19 @@ "homepage": "https://sagikazarmark.hu" } ], + "repositories": [ + { + "type": "package", + "package": { + "name": "jshttp/mime-db", + "version": "1.54.0.1", + "dist": { + "url": "https://codeload.github.com/jshttp/mime-db/zip/0a9fd0bfbc87a725ff638495839114e7807b7177", + "type": "zip" + } + } + } + ], "require": { "php": "^7.2.5 || ^8.0", "psr/http-factory": "^1.0", @@ -62,6 +75,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", + "jshttp/mime-db": "1.54.0.1", "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { diff --git a/lib/guzzlehttp/psr7/src/LimitStream.php b/lib/guzzlehttp/psr7/src/LimitStream.php index fb2232557..c6676f559 100644 --- a/lib/guzzlehttp/psr7/src/LimitStream.php +++ b/lib/guzzlehttp/psr7/src/LimitStream.php @@ -63,9 +63,9 @@ final class LimitStream implements StreamInterface return null; } elseif ($this->limit === -1) { return $length - $this->offset; - } else { - return min($this->limit, $length - $this->offset); } + + return min($this->limit, $length - $this->offset); } /** diff --git a/lib/guzzlehttp/psr7/src/MessageTrait.php b/lib/guzzlehttp/psr7/src/MessageTrait.php index c15ee63fc..f612ca1b9 100644 --- a/lib/guzzlehttp/psr7/src/MessageTrait.php +++ b/lib/guzzlehttp/psr7/src/MessageTrait.php @@ -29,6 +29,9 @@ trait MessageTrait return $this->protocol; } + /** + * @return static + */ public function withProtocolVersion($version): MessageInterface { if ($this->protocol === $version) { @@ -69,6 +72,9 @@ trait MessageTrait return implode(', ', $this->getHeader($header)); } + /** + * @return static + */ public function withHeader($header, $value): MessageInterface { $this->assertHeader($header); @@ -85,6 +91,9 @@ trait MessageTrait return $new; } + /** + * @return static + */ public function withAddedHeader($header, $value): MessageInterface { $this->assertHeader($header); @@ -103,6 +112,9 @@ trait MessageTrait return $new; } + /** + * @return static + */ public function withoutHeader($header): MessageInterface { $normalized = strtolower($header); @@ -128,6 +140,9 @@ trait MessageTrait return $this->stream; } + /** + * @return static + */ public function withBody(StreamInterface $body): MessageInterface { if ($body === $this->stream) { diff --git a/lib/guzzlehttp/psr7/src/MimeType.php b/lib/guzzlehttp/psr7/src/MimeType.php index b131bdbe7..fa493b861 100644 --- a/lib/guzzlehttp/psr7/src/MimeType.php +++ b/lib/guzzlehttp/psr7/src/MimeType.php @@ -7,22 +7,23 @@ namespace GuzzleHttp\Psr7; final class MimeType { private const MIME_TYPES = [ + '123' => 'application/vnd.lotus-1-2-3', '1km' => 'application/vnd.1000minds.decision-model+xml', + '210' => 'model/step', '3dml' => 'text/vnd.in3d.3dml', '3ds' => 'image/x-3ds', '3g2' => 'video/3gpp2', - '3gp' => 'video/3gp', + '3gp' => 'video/3gpp', '3gpp' => 'video/3gpp', '3mf' => 'model/3mf', '7z' => 'application/x-7z-compressed', '7zip' => 'application/x-7z-compressed', - '123' => 'application/vnd.lotus-1-2-3', 'aab' => 'application/x-authorware-bin', 'aac' => 'audio/aac', 'aam' => 'application/x-authorware-map', 'aas' => 'application/x-authorware-seg', 'abw' => 'application/x-abiword', - 'ac' => 'application/vnd.nokia.n-gage.ac+xml', + 'ac' => 'application/pkix-attr-cert', 'ac3' => 'audio/ac3', 'acc' => 'application/vnd.americandynamics.acc', 'ace' => 'application/x-ace-compressed', @@ -35,7 +36,7 @@ final class MimeType 'afp' => 'application/vnd.ibm.modcap', 'age' => 'application/vnd.age', 'ahead' => 'application/vnd.ahead.space', - 'ai' => 'application/pdf', + 'ai' => 'application/postscript', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', @@ -55,7 +56,7 @@ final class MimeType 'apr' => 'application/vnd.lotus-approach', 'arc' => 'application/x-freearc', 'arj' => 'application/x-arj', - 'asc' => 'application/pgp-signature', + 'asc' => 'application/pgp-keys', 'asf' => 'video/x-ms-asf', 'asm' => 'text/x-asm', 'aso' => 'application/vnd.accpac.simply.aso', @@ -66,7 +67,7 @@ final class MimeType 'atomdeleted' => 'application/atomdeleted+xml', 'atomsvc' => 'application/atomsvc+xml', 'atx' => 'application/vnd.antix.game-component', - 'au' => 'audio/x-au', + 'au' => 'audio/basic', 'avci' => 'image/avci', 'avcs' => 'image/avcs', 'avi' => 'video/x-msvideo', @@ -77,15 +78,18 @@ final class MimeType 'azv' => 'image/vnd.airzip.accelerator.azv', 'azw' => 'application/vnd.amazon.ebook', 'b16' => 'image/vnd.pco.b16', + 'bary' => 'model/vnd.bary', 'bat' => 'application/x-msdownload', 'bcpio' => 'application/x-bcpio', 'bdf' => 'application/x-font-bdf', 'bdm' => 'application/vnd.syncml.dm+wbxml', - 'bdoc' => 'application/x-bdoc', + 'bdo' => 'application/vnd.nato.bindingdataobject+xml', + 'bdoc' => 'application/bdoc', 'bed' => 'application/vnd.realvnc.bed', 'bh2' => 'application/vnd.fujitsu.oasysprs', 'bin' => 'application/octet-stream', 'blb' => 'application/x-blorb', + 'blend' => 'application/x-blender', 'blorb' => 'application/x-blorb', 'bmi' => 'application/vnd.bmi', 'bmml' => 'application/vnd.balsamiq.bmml+xml', @@ -95,6 +99,8 @@ final class MimeType 'boz' => 'application/x-bzip2', 'bpk' => 'application/octet-stream', 'bpmn' => 'application/octet-stream', + 'brush' => 'application/vnd.procreate.brush', + 'brushset' => 'application/vnd.procreate.brushset', 'bsp' => 'model/vnd.valve.source.compiled-map', 'btf' => 'image/prs.btif', 'btif' => 'image/prs.btif', @@ -102,13 +108,13 @@ final class MimeType 'bz' => 'application/x-bzip', 'bz2' => 'application/x-bzip2', 'c' => 'text/x-c', + 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', + 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', 'c4d' => 'application/vnd.clonk.c4group', 'c4f' => 'application/vnd.clonk.c4group', 'c4g' => 'application/vnd.clonk.c4group', 'c4p' => 'application/vnd.clonk.c4group', 'c4u' => 'application/vnd.clonk.c4group', - 'c11amc' => 'application/vnd.cluetrust.cartomobile-config', - 'c11amz' => 'application/vnd.cluetrust.cartomobile-config-pkg', 'cab' => 'application/vnd.ms-cab-compressed', 'caf' => 'audio/x-caf', 'cap' => 'application/vnd.tcpdump.pcap', @@ -132,7 +138,6 @@ final class MimeType 'cdmid' => 'application/cdmi-domain', 'cdmio' => 'application/cdmi-object', 'cdmiq' => 'application/cdmi-queue', - 'cdr' => 'application/cdr', 'cdx' => 'chemical/x-cdx', 'cdxml' => 'application/vnd.chemdraw+xml', 'cdy' => 'application/vnd.cinderella', @@ -147,7 +152,7 @@ final class MimeType 'cil' => 'application/vnd.ms-artgalry', 'cjs' => 'application/node', 'cla' => 'application/vnd.claymore', - 'class' => 'application/octet-stream', + 'class' => 'application/java-vm', 'cld' => 'model/vnd.cld', 'clkk' => 'application/vnd.crick.clicker.keyboard', 'clkp' => 'application/vnd.crick.clicker.palette', @@ -194,6 +199,8 @@ final class MimeType 'davmount' => 'application/davmount+xml', 'dbf' => 'application/vnd.dbf', 'dbk' => 'application/docbook+xml', + 'dcm' => 'application/dicom', + 'dcmp' => 'application/vnd.dcmp+xml', 'dcr' => 'application/x-director', 'dcurl' => 'text/vnd.curl.dcurl', 'dd2' => 'application/vnd.oma.dd2+xml', @@ -221,19 +228,22 @@ final class MimeType 'dmp' => 'application/vnd.tcpdump.pcap', 'dms' => 'application/octet-stream', 'dna' => 'application/vnd.dna', + 'dng' => 'image/x-adobe-dng', 'doc' => 'application/msword', - 'docm' => 'application/vnd.ms-word.template.macroEnabled.12', + 'docm' => 'application/vnd.ms-word.document.macroenabled.12', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dot' => 'application/msword', - 'dotm' => 'application/vnd.ms-word.template.macroEnabled.12', + 'dotm' => 'application/vnd.ms-word.template.macroenabled.12', 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'dp' => 'application/vnd.osgi.dp', 'dpg' => 'application/vnd.dpgraph', 'dpx' => 'image/dpx', 'dra' => 'audio/vnd.dra', 'drle' => 'image/dicom-rle', + 'drm' => 'application/vnd.procreate.dream', 'dsc' => 'text/prs.lines.tag', 'dssc' => 'application/dssc+der', + 'dst' => 'application/octet-stream', 'dtb' => 'application/x-dtbook+xml', 'dtd' => 'application/xml-dtd', 'dts' => 'audio/vnd.dts', @@ -285,10 +295,12 @@ final class MimeType 'f4v' => 'video/mp4', 'f77' => 'text/x-fortran', 'f90' => 'text/x-fortran', + 'facti' => 'image/vnd.blockfact.facti', 'fbs' => 'image/vnd.fastbidsheet', + 'fbx' => 'application/vnd.autodesk.fbx', 'fcdt' => 'application/vnd.adobe.formscentral.fcdt', 'fcs' => 'application/vnd.isac.fcs', - 'fdf' => 'application/vnd.fdf', + 'fdf' => 'application/fdf', 'fdt' => 'application/fdt+xml', 'fe_launch' => 'application/vnd.denovo.fcselayout-link', 'fg5' => 'application/vnd.fujitsu.oasysgp', @@ -330,21 +342,25 @@ final class MimeType 'gca' => 'application/x-gca-compressed', 'gdl' => 'model/vnd.gdl', 'gdoc' => 'application/vnd.google-apps.document', + 'gdraw' => 'application/vnd.google-apps.drawing', 'ged' => 'text/vnd.familysearch.gedcom', 'geo' => 'application/vnd.dynageo', 'geojson' => 'application/geo+json', 'gex' => 'application/vnd.geometry-explorer', + 'gform' => 'application/vnd.google-apps.form', 'ggb' => 'application/vnd.geogebra.file', + 'ggs' => 'application/vnd.geogebra.slides', 'ggt' => 'application/vnd.geogebra.tool', 'ghf' => 'application/vnd.groove-help', 'gif' => 'image/gif', 'gim' => 'application/vnd.groove-identity-message', + 'gjam' => 'application/vnd.google-apps.jam', 'glb' => 'model/gltf-binary', 'gltf' => 'model/gltf+json', + 'gmap' => 'application/vnd.google-apps.map', 'gml' => 'application/gml+xml', 'gmx' => 'application/vnd.gmx', 'gnumeric' => 'application/x-gnumeric', - 'gpg' => 'application/gpg-keys', 'gph' => 'application/vnd.flographit', 'gpx' => 'application/gpx+xml', 'gqf' => 'application/vnd.grafeq', @@ -354,8 +370,10 @@ final class MimeType 'gre' => 'application/vnd.geometry-explorer', 'grv' => 'application/vnd.groove-injector', 'grxml' => 'application/srgs+xml', + 'gscript' => 'application/vnd.google-apps.script', 'gsf' => 'application/x-font-ghostscript', 'gsheet' => 'application/vnd.google-apps.spreadsheet', + 'gsite' => 'application/vnd.google-apps.site', 'gslides' => 'application/vnd.google-apps.presentation', 'gtar' => 'application/x-gtar', 'gtm' => 'application/vnd.groove-tool-message', @@ -387,7 +405,6 @@ final class MimeType 'hpid' => 'application/vnd.hp-hpid', 'hps' => 'application/vnd.hp-hps', 'hqx' => 'application/mac-binhex40', - 'hsj2' => 'image/hsj2', 'htc' => 'text/x-component', 'htke' => 'application/vnd.kenameaapp', 'htm' => 'text/html', @@ -399,7 +416,7 @@ final class MimeType 'icc' => 'application/vnd.iccprofile', 'ice' => 'x-conference/x-cooltalk', 'icm' => 'application/vnd.iccprofile', - 'ico' => 'image/x-icon', + 'ico' => 'image/vnd.microsoft.icon', 'ics' => 'text/calendar', 'ief' => 'image/ief', 'ifb' => 'text/calendar', @@ -414,6 +431,7 @@ final class MimeType 'imp' => 'application/vnd.accpac.simply.imp', 'ims' => 'application/vnd.ms-ims', 'in' => 'text/plain', + 'indd' => 'application/x-indesign', 'ini' => 'text/plain', 'ink' => 'application/inkml+xml', 'inkml' => 'application/inkml+xml', @@ -421,6 +439,7 @@ final class MimeType 'iota' => 'application/vnd.astraea-software.iota', 'ipfix' => 'application/ipfix', 'ipk' => 'application/vnd.shana.informed.package', + 'ipynb' => 'application/x-ipynb+json', 'irm' => 'application/vnd.ibm.rights-management', 'irp' => 'application/vnd.irepository.package+xml', 'iso' => 'application/x-iso9660-image', @@ -430,10 +449,13 @@ final class MimeType 'ivu' => 'application/vnd.immervision-ivu', 'jad' => 'text/vnd.sun.j2me.app-descriptor', 'jade' => 'text/jade', + 'jaii' => 'image/jaii', + 'jais' => 'image/jais', 'jam' => 'application/vnd.jam', 'jar' => 'application/java-archive', 'jardiff' => 'application/x-java-archive-diff', 'java' => 'text/x-java-source', + 'jfif' => 'image/jpeg', 'jhc' => 'image/jphc', 'jisp' => 'application/vnd.jisp', 'jls' => 'image/jls', @@ -447,18 +469,19 @@ final class MimeType 'jpf' => 'image/jpx', 'jpg' => 'image/jpeg', 'jpg2' => 'image/jp2', - 'jpgm' => 'video/jpm', + 'jpgm' => 'image/jpm', 'jpgv' => 'video/jpeg', 'jph' => 'image/jph', - 'jpm' => 'video/jpm', + 'jpm' => 'image/jpm', 'jpx' => 'image/jpx', - 'js' => 'application/javascript', + 'js' => 'text/javascript', 'json' => 'application/json', 'json5' => 'application/json5', 'jsonld' => 'application/ld+json', 'jsonml' => 'application/jsonml+json', 'jsx' => 'text/jsx', 'jt' => 'model/jt', + 'jxl' => 'image/jxl', 'jxr' => 'image/jxr', 'jxra' => 'image/jxra', 'jxrs' => 'image/jxrs', @@ -468,9 +491,10 @@ final class MimeType 'jxss' => 'image/jxss', 'kar' => 'audio/midi', 'karbon' => 'application/vnd.kde.karbon', + 'kbl' => 'application/kbl+xml', 'kdb' => 'application/octet-stream', 'kdbx' => 'application/x-keepass2', - 'key' => 'application/x-iwork-keynote-sffkey', + 'key' => 'application/vnd.apple.keynote', 'kfo' => 'application/vnd.kde.kformula', 'kia' => 'application/vnd.kidspiration', 'kml' => 'application/vnd.google-earth.kml+xml', @@ -495,7 +519,7 @@ final class MimeType 'les' => 'application/vnd.hhe.lesson-player', 'less' => 'text/less', 'lgr' => 'application/lgr+xml', - 'lha' => 'application/octet-stream', + 'lha' => 'application/x-lzh-compressed', 'link66' => 'application/vnd.route66.link66+xml', 'list' => 'text/plain', 'list3820' => 'application/vnd.ibm.modcap', @@ -504,6 +528,7 @@ final class MimeType 'lnk' => 'application/x-ms-shortcut', 'log' => 'text/plain', 'lostxml' => 'application/lost+xml', + 'lottie' => 'application/zip+dotlottie', 'lrf' => 'application/octet-stream', 'lrm' => 'application/vnd.ms-lrm', 'ltf' => 'application/vnd.frogans.ltf', @@ -511,21 +536,24 @@ final class MimeType 'luac' => 'application/x-lua-bytecode', 'lvp' => 'audio/vnd.lucent.voice', 'lwp' => 'application/vnd.lotus-wordpro', - 'lzh' => 'application/octet-stream', - 'm1v' => 'video/mpeg', - 'm2a' => 'audio/mpeg', - 'm2v' => 'video/mpeg', - 'm3a' => 'audio/mpeg', - 'm3u' => 'text/plain', - 'm3u8' => 'application/vnd.apple.mpegurl', - 'm4a' => 'audio/x-m4a', - 'm4p' => 'application/mp4', - 'm4s' => 'video/iso.segment', - 'm4u' => 'application/vnd.mpegurl', - 'm4v' => 'video/x-m4v', + 'lzh' => 'application/x-lzh-compressed', 'm13' => 'application/x-msmediaview', 'm14' => 'application/x-msmediaview', + 'm1v' => 'video/mpeg', 'm21' => 'application/mp21', + 'm2a' => 'audio/mpeg', + 'm2t' => 'video/mp2t', + 'm2ts' => 'video/mp2t', + 'm2v' => 'video/mpeg', + 'm3a' => 'audio/mpeg', + 'm3u' => 'audio/x-mpegurl', + 'm3u8' => 'application/vnd.apple.mpegurl', + 'm4a' => 'audio/mp4', + 'm4b' => 'audio/mp4', + 'm4p' => 'application/mp4', + 'm4s' => 'video/iso.segment', + 'm4u' => 'video/vnd.mpegurl', + 'm4v' => 'video/x-m4v', 'ma' => 'application/mathematica', 'mads' => 'application/mads+xml', 'maei' => 'application/mmt-aei+xml', @@ -556,6 +584,8 @@ final class MimeType 'mft' => 'application/rpki-manifest', 'mgp' => 'application/vnd.osgeo.mapguide.package', 'mgz' => 'application/vnd.proteus.magazine', + 'mht' => 'message/rfc822', + 'mhtml' => 'message/rfc822', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mie' => 'application/x-mie', @@ -564,11 +594,11 @@ final class MimeType 'mj2' => 'video/mj2', 'mjp2' => 'video/mj2', 'mjs' => 'text/javascript', - 'mk3d' => 'video/x-matroska', - 'mka' => 'audio/x-matroska', + 'mk3d' => 'video/matroska-3d', + 'mka' => 'audio/matroska', 'mkd' => 'text/x-markdown', 'mks' => 'video/x-matroska', - 'mkv' => 'video/x-matroska', + 'mkv' => 'video/matroska', 'mlp' => 'application/vnd.dolby.mlp', 'mmd' => 'application/vnd.chipnuts.karaoke-mmd', 'mmf' => 'application/vnd.smaf', @@ -581,13 +611,13 @@ final class MimeType 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mp2' => 'audio/mpeg', + 'mp21' => 'application/mp21', 'mp2a' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', 'mp4s' => 'application/mp4', 'mp4v' => 'video/mp4', - 'mp21' => 'application/mp21', 'mpc' => 'application/vnd.mophun.certificate', 'mpd' => 'application/dash+xml', 'mpe' => 'video/mpeg', @@ -612,7 +642,7 @@ final class MimeType 'msf' => 'application/vnd.epson.msf', 'msg' => 'application/vnd.ms-outlook', 'msh' => 'model/mesh', - 'msi' => 'application/x-msdownload', + 'msi' => 'application/octet-stream', 'msix' => 'application/msix', 'msixbundle' => 'application/msixbundle', 'msl' => 'application/vnd.mobius.msl', @@ -620,7 +650,7 @@ final class MimeType 'msp' => 'application/octet-stream', 'msty' => 'application/vnd.muvee.style', 'mtl' => 'model/mtl', - 'mts' => 'model/vnd.mts', + 'mts' => 'video/mp2t', 'mus' => 'application/vnd.musician', 'musd' => 'application/mmt-usd+xml', 'musicxml' => 'application/vnd.recordare.musicxml+xml', @@ -639,6 +669,7 @@ final class MimeType 'nbp' => 'application/vnd.wolfram.player', 'nc' => 'application/x-netcdf', 'ncx' => 'application/x-dtbncx+xml', + 'ndjson' => 'application/x-ndjson', 'nfo' => 'text/x-nfo', 'ngdat' => 'application/vnd.nokia.n-gage.data', 'nitf' => 'application/vnd.nitf', @@ -653,7 +684,7 @@ final class MimeType 'nsf' => 'application/vnd.lotus-notes', 'nt' => 'application/n-triples', 'ntf' => 'application/vnd.nitf', - 'numbers' => 'application/x-iwork-numbers-sffnumbers', + 'numbers' => 'application/vnd.apple.numbers', 'nzb' => 'application/x-nzb', 'oa2' => 'application/vnd.fujitsu.oasys2', 'oa3' => 'application/vnd.fujitsu.oasys3', @@ -678,6 +709,8 @@ final class MimeType 'ogv' => 'video/ogg', 'ogx' => 'application/ogg', 'omdoc' => 'application/omdoc+xml', + 'one' => 'application/onenote', + 'onea' => 'application/onenote', 'onepkg' => 'application/onenote', 'onetmp' => 'application/onenote', 'onetoc' => 'application/onenote', @@ -686,7 +719,7 @@ final class MimeType 'opml' => 'text/x-opml', 'oprc' => 'application/vnd.palm', 'opus' => 'audio/ogg', - 'org' => 'text/x-org', + 'org' => 'application/vnd.lotus-organizer', 'osf' => 'application/vnd.yamaha.openscoreformat', 'osfpvg' => 'application/vnd.yamaha.openscoreformat.osfpvg+xml', 'osm' => 'application/vnd.openstreetmap.data+xml', @@ -704,17 +737,20 @@ final class MimeType 'oxps' => 'application/oxps', 'oxt' => 'application/vnd.openofficeorg.extension', 'p' => 'text/x-pascal', + 'p10' => 'application/pkcs10', + 'p12' => 'application/x-pkcs12', + 'p21' => 'model/step', 'p7a' => 'application/x-pkcs7-signature', 'p7b' => 'application/x-pkcs7-certificates', 'p7c' => 'application/pkcs7-mime', + 'p7e' => 'application/pkcs7-mime', 'p7m' => 'application/pkcs7-mime', 'p7r' => 'application/x-pkcs7-certreqresp', 'p7s' => 'application/pkcs7-signature', 'p8' => 'application/pkcs8', - 'p10' => 'application/x-pkcs10', - 'p12' => 'application/x-pkcs12', 'pac' => 'application/x-ns-proxy-autoconfig', - 'pages' => 'application/x-iwork-pages-sffpages', + 'pages' => 'application/vnd.apple.pages', + 'parquet' => 'application/vnd.apache.parquet', 'pas' => 'text/x-pascal', 'paw' => 'application/vnd.pawaafile', 'pbd' => 'application/vnd.powerbuilder6', @@ -725,8 +761,8 @@ final class MimeType 'pclxl' => 'application/vnd.hp-pclxl', 'pct' => 'image/x-pict', 'pcurl' => 'application/vnd.curl.pcurl', - 'pcx' => 'image/x-pcx', - 'pdb' => 'application/x-pilot', + 'pcx' => 'image/vnd.zbrush.pcx', + 'pdb' => 'application/vnd.palm', 'pde' => 'text/x-processing', 'pdf' => 'application/pdf', 'pem' => 'application/x-x509-user-cert', @@ -737,7 +773,7 @@ final class MimeType 'pfx' => 'application/x-pkcs12', 'pgm' => 'image/x-portable-graymap', 'pgn' => 'application/x-chess-pgn', - 'pgp' => 'application/pgp', + 'pgp' => 'application/pgp-encrypted', 'phar' => 'application/octet-stream', 'php' => 'application/x-httpd-php', 'php3' => 'application/x-httpd-php', @@ -760,17 +796,17 @@ final class MimeType 'pnm' => 'image/x-portable-anymap', 'portpkg' => 'application/vnd.macports.portpkg', 'pot' => 'application/vnd.ms-powerpoint', - 'potm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'potm' => 'application/vnd.ms-powerpoint.template.macroenabled.12', 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ppa' => 'application/vnd.ms-powerpoint', - 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'ppam' => 'application/vnd.ms-powerpoint.addin.macroenabled.12', 'ppd' => 'application/vnd.cups-ppd', 'ppm' => 'image/x-portable-pixmap', 'pps' => 'application/vnd.ms-powerpoint', - 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12', + 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroenabled.12', 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'ppt' => 'application/powerpoint', - 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroenabled.12', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'pqa' => 'application/vnd.palm', 'prc' => 'model/prc', @@ -779,14 +815,16 @@ final class MimeType 'provx' => 'application/provenance+xml', 'ps' => 'application/postscript', 'psb' => 'application/vnd.3gpp.pic-bw-small', - 'psd' => 'application/x-photoshop', + 'psd' => 'image/vnd.adobe.photoshop', 'psf' => 'application/x-font-linux-psf', 'pskcxml' => 'application/pskc+xml', 'pti' => 'image/prs.pti', 'ptid' => 'application/vnd.pvi.ptid1', 'pub' => 'application/x-mspublisher', + 'pv' => 'application/octet-stream', 'pvb' => 'application/vnd.3gpp.pic-bw-var', 'pwn' => 'application/vnd.3m.post-it-notes', + 'pxf' => 'application/octet-stream', 'pya' => 'audio/vnd.ms-playready.media.pya', 'pyo' => 'model/vnd.pytha.pyox', 'pyox' => 'model/vnd.pytha.pyox', @@ -806,7 +844,7 @@ final class MimeType 'ram' => 'audio/x-pn-realaudio', 'raml' => 'application/raml+yaml', 'rapd' => 'application/route-apd+xml', - 'rar' => 'application/x-rar', + 'rar' => 'application/vnd.rar', 'ras' => 'image/x-cmu-raster', 'rcprofile' => 'application/vnd.ipunplugged.rcprofile', 'rdf' => 'application/rdf+xml', @@ -821,7 +859,7 @@ final class MimeType 'rl' => 'application/resource-lists+xml', 'rlc' => 'image/vnd.fujixerox.edmics-rlc', 'rld' => 'application/resource-lists-diff+xml', - 'rm' => 'audio/x-pn-realaudio', + 'rm' => 'application/vnd.rn-realmedia', 'rmi' => 'audio/midi', 'rmp' => 'audio/x-pn-realaudio-plugin', 'rms' => 'application/vnd.jcp.javame.midlet-rms', @@ -831,7 +869,7 @@ final class MimeType 'roa' => 'application/rpki-roa', 'roff' => 'text/troff', 'rp9' => 'application/vnd.cloanto.rp9', - 'rpm' => 'audio/x-pn-realaudio-plugin', + 'rpm' => 'application/x-redhat-package-manager', 'rpss' => 'application/vnd.nokia.radio-presets', 'rpst' => 'application/vnd.nokia.radio-preset', 'rq' => 'application/sparql-query', @@ -865,7 +903,7 @@ final class MimeType 'sdkm' => 'application/vnd.solent.sdkm+xml', 'sdp' => 'application/sdp', 'sdw' => 'application/vnd.stardivision.writer', - 'sea' => 'application/octet-stream', + 'sea' => 'application/x-sea', 'see' => 'application/vnd.seemail', 'seed' => 'application/vnd.fdsn.seed', 'sema' => 'application/vnd.sema', @@ -910,8 +948,8 @@ final class MimeType 'slt' => 'application/vnd.epson.salt', 'sm' => 'application/vnd.stepmania.stepchart', 'smf' => 'application/vnd.stardivision.math', - 'smi' => 'application/smil', - 'smil' => 'application/smil', + 'smi' => 'application/smil+xml', + 'smil' => 'application/smil+xml', 'smv' => 'video/x-smv', 'smzip' => 'application/vnd.stepmania.package', 'snd' => 'audio/basic', @@ -925,7 +963,9 @@ final class MimeType 'spp' => 'application/scvp-vp-response', 'spq' => 'application/scvp-vp-request', 'spx' => 'audio/ogg', - 'sql' => 'application/x-sql', + 'sql' => 'application/sql', + 'sqlite' => 'application/vnd.sqlite3', + 'sqlite3' => 'application/vnd.sqlite3', 'src' => 'application/x-wais-source', 'srt' => 'application/x-subrip', 'sru' => 'application/sru+xml', @@ -938,12 +978,13 @@ final class MimeType 'st' => 'application/vnd.sailingtracker.track', 'stc' => 'application/vnd.sun.xml.calc.template', 'std' => 'application/vnd.sun.xml.draw.template', - 'step' => 'application/STEP', + 'step' => 'model/step', 'stf' => 'application/vnd.wt.stf', 'sti' => 'application/vnd.sun.xml.impress.template', 'stk' => 'application/hyperstudio', 'stl' => 'model/stl', - 'stp' => 'application/STEP', + 'stp' => 'model/step', + 'stpnc' => 'model/step', 'stpx' => 'model/step+xml', 'stpxz' => 'model/step-xml+zip', 'stpz' => 'model/step+zip', @@ -951,7 +992,7 @@ final class MimeType 'stw' => 'application/vnd.sun.xml.writer.template', 'styl' => 'text/stylus', 'stylus' => 'text/stylus', - 'sub' => 'text/vnd.dvb.subtitle', + 'sub' => 'image/vnd.dvb.subtitle', 'sus' => 'application/vnd.sus-calendar', 'susp' => 'application/vnd.sus-calendar', 'sv4cpio' => 'application/x-sv4cpio', @@ -970,6 +1011,7 @@ final class MimeType 'sxi' => 'application/vnd.sun.xml.impress', 'sxm' => 'application/vnd.sun.xml.math', 'sxw' => 'application/vnd.sun.xml.writer', + 'systemverify' => 'application/vnd.pp.systemverify+xml', 't' => 'text/troff', 't3' => 'application/x-t3vm-image', 't38' => 'image/t38', @@ -991,7 +1033,7 @@ final class MimeType 'tfm' => 'application/x-tex-tfm', 'tfx' => 'image/tiff-fx', 'tga' => 'image/x-tga', - 'tgz' => 'application/x-tar', + 'tgz' => 'application/gzip', 'thmx' => 'application/vnd.ms-officetheme', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', @@ -1017,12 +1059,12 @@ final class MimeType 'txd' => 'application/vnd.genomatix.tuxedo', 'txf' => 'application/vnd.mobius.txf', 'txt' => 'text/plain', + 'u32' => 'application/x-authorware-bin', 'u3d' => 'model/u3d', 'u8dsn' => 'message/global-delivery-status', 'u8hdr' => 'message/global-headers', 'u8mdn' => 'message/global-disposition-notification', 'u8msg' => 'message/global', - 'u32' => 'application/x-authorware-bin', 'ubj' => 'application/ubjson', 'udeb' => 'application/x-debian-package', 'ufd' => 'application/vnd.ufdl', @@ -1078,16 +1120,18 @@ final class MimeType 'vcx' => 'application/vnd.vcx', 'vdi' => 'application/x-virtualbox-vdi', 'vds' => 'model/vnd.sap.vds', + 'vdx' => 'application/vnd.ms-visio.viewer', + 'vec' => 'application/vec+xml', 'vhd' => 'application/x-virtualbox-vhd', 'vis' => 'application/vnd.visionary', 'viv' => 'video/vnd.vivo', - 'vlc' => 'application/videolan', 'vmdk' => 'application/x-virtualbox-vmdk', 'vob' => 'video/x-ms-vob', 'vor' => 'application/vnd.stardivision.writer', 'vox' => 'application/x-authorware-bin', 'vrml' => 'model/vrml', 'vsd' => 'application/vnd.visio', + 'vsdx' => 'application/vnd.visio', 'vsf' => 'application/vnd.vsf', 'vss' => 'application/vnd.visio', 'vst' => 'application/vnd.visio', @@ -1095,17 +1139,18 @@ final class MimeType 'vtf' => 'image/vnd.valve.source.texture', 'vtt' => 'text/vtt', 'vtu' => 'model/vnd.vtu', + 'vtx' => 'application/vnd.visio', 'vxml' => 'application/voicexml+xml', 'w3d' => 'application/x-director', 'wad' => 'application/x-doom', 'wadl' => 'application/vnd.sun.wadl+xml', 'war' => 'application/java-archive', 'wasm' => 'application/wasm', - 'wav' => 'audio/x-wav', + 'wav' => 'audio/wav', 'wax' => 'audio/x-ms-wax', 'wbmp' => 'image/vnd.wap.wbmp', 'wbs' => 'application/vnd.criticaltools.wbs+xml', - 'wbxml' => 'application/wbxml', + 'wbxml' => 'application/vnd.wap.wbxml', 'wcm' => 'application/vnd.ms-works', 'wdb' => 'application/vnd.ms-works', 'wdp' => 'image/vnd.ms-photo', @@ -1124,12 +1169,12 @@ final class MimeType 'wmd' => 'application/x-ms-wmd', 'wmf' => 'image/wmf', 'wml' => 'text/vnd.wap.wml', - 'wmlc' => 'application/wmlc', + 'wmlc' => 'application/vnd.wap.wmlc', 'wmls' => 'text/vnd.wap.wmlscript', 'wmlsc' => 'application/vnd.wap.wmlscriptc', 'wmv' => 'video/x-ms-wmv', 'wmx' => 'video/x-ms-wmx', - 'wmz' => 'application/x-msmetafile', + 'wmz' => 'application/x-ms-wmz', 'woff' => 'font/woff', 'woff2' => 'font/woff2', 'word' => 'application/msword', @@ -1144,13 +1189,13 @@ final class MimeType 'wspolicy' => 'application/wspolicy+xml', 'wtb' => 'application/vnd.webturbo', 'wvx' => 'video/x-ms-wvx', + 'x32' => 'application/x-authorware-bin', 'x3d' => 'model/x3d+xml', 'x3db' => 'model/x3d+fastinfoset', 'x3dbz' => 'model/x3d+binary', 'x3dv' => 'model/x3d-vrml', 'x3dvz' => 'model/x3d+vrml', 'x3dz' => 'model/x3d+xml', - 'x32' => 'application/x-authorware-bin', 'x_b' => 'model/vnd.parasolid.transmit.binary', 'x_t' => 'model/vnd.parasolid.transmit.text', 'xaml' => 'application/xaml+xml', @@ -1162,6 +1207,7 @@ final class MimeType 'xbm' => 'image/x-xbitmap', 'xca' => 'application/xcap-caps+xml', 'xcs' => 'application/calendar+xml', + 'xdcf' => 'application/vnd.gov.sk.xmldatacontainer+xml', 'xdf' => 'application/xcap-diff+xml', 'xdm' => 'application/vnd.syncml.dm+xml', 'xdp' => 'application/vnd.adobe.xdp+xml', @@ -1177,18 +1223,18 @@ final class MimeType 'xhtml' => 'application/xhtml+xml', 'xhvml' => 'application/xv+xml', 'xif' => 'image/vnd.xiff', - 'xl' => 'application/excel', + 'xl' => 'application/vnd.ms-excel', 'xla' => 'application/vnd.ms-excel', - 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlam' => 'application/vnd.ms-excel.addin.macroenabled.12', 'xlc' => 'application/vnd.ms-excel', 'xlf' => 'application/xliff+xml', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel', - 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', - 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroenabled.12', + 'xlsm' => 'application/vnd.ms-excel.sheet.macroenabled.12', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlt' => 'application/vnd.ms-excel', - 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12', + 'xltm' => 'application/vnd.ms-excel.template.macroenabled.12', 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'xlw' => 'application/vnd.ms-excel', 'xm' => 'audio/xm', @@ -1205,7 +1251,7 @@ final class MimeType 'xpx' => 'application/vnd.intercon.formnet', 'xsd' => 'application/xml', 'xsf' => 'application/prs.xsf+xml', - 'xsl' => 'application/xml', + 'xsl' => 'application/xslt+xml', 'xslt' => 'application/xslt+xml', 'xsm' => 'application/vnd.syncml+xml', 'xspf' => 'application/xspf+xml', diff --git a/lib/guzzlehttp/psr7/src/MultipartStream.php b/lib/guzzlehttp/psr7/src/MultipartStream.php index 43d718f65..bca326a51 100644 --- a/lib/guzzlehttp/psr7/src/MultipartStream.php +++ b/lib/guzzlehttp/psr7/src/MultipartStream.php @@ -23,11 +23,18 @@ final class MultipartStream implements StreamInterface /** * @param array $elements Array of associative arrays, each containing a * required "name" key mapping to the form field, - * name, a required "contents" key mapping to a - * StreamInterface/resource/string, an optional - * "headers" associative array of custom headers, - * and an optional "filename" key mapping to a - * string to send as the filename in the part. + * name, a required "contents" key mapping to any + * value accepted by Utils::streamFor() (scalar, + * null, resource, StreamInterface, Iterator, or + * callable), or an array for nested expansion. + * Optional keys include "headers" (associative + * array of custom headers) and "filename" (string + * to send as the filename in the part). + * When "contents" is an array, it is recursively + * expanded into multiple fields using bracket notation + * (e.g., name[0][key]). Empty arrays produce no fields. + * The "filename" and "headers" options cannot be used + * with array contents. * @param string $boundary You can optionally provide a specific boundary * * @throws \InvalidArgumentException @@ -91,6 +98,22 @@ final class MultipartStream implements StreamInterface } } + if (!is_string($element['name']) && !is_int($element['name'])) { + throw new \InvalidArgumentException("The 'name' key must be a string or integer"); + } + + if (is_array($element['contents'])) { + if (array_key_exists('filename', $element) || array_key_exists('headers', $element)) { + throw new \InvalidArgumentException( + "The 'filename' and 'headers' options cannot be used when 'contents' is an array" + ); + } + + $this->addNestedElements($stream, $element['contents'], (string) $element['name']); + + return; + } + $element['contents'] = Utils::streamFor($element['contents']); if (empty($element['filename'])) { @@ -101,7 +124,7 @@ final class MultipartStream implements StreamInterface } [$body, $headers] = $this->createElement( - $element['name'], + (string) $element['name'], $element['contents'], $element['filename'] ?? null, $element['headers'] ?? [] @@ -112,6 +135,24 @@ final class MultipartStream implements StreamInterface $stream->addStream(Utils::streamFor("\r\n")); } + /** + * Recursively expand array contents into multiple form fields. + * + * @param array $contents + */ + private function addNestedElements(AppendStream $stream, array $contents, string $root): void + { + foreach ($contents as $key => $value) { + $fieldName = $root === '' ? sprintf('[%s]', (string) $key) : sprintf('%s[%s]', $root, (string) $key); + + if (is_array($value)) { + $this->addNestedElements($stream, $value, $fieldName); + } else { + $this->addElement($stream, ['name' => $fieldName, 'contents' => $value]); + } + } + } + /** * @param string[] $headers * diff --git a/lib/guzzlehttp/psr7/src/Request.php b/lib/guzzlehttp/psr7/src/Request.php index faafe1ad8..b63bcac56 100644 --- a/lib/guzzlehttp/psr7/src/Request.php +++ b/lib/guzzlehttp/psr7/src/Request.php @@ -40,7 +40,7 @@ class Request implements RequestInterface string $version = '1.1' ) { $this->assertMethod($method); - if (!($uri instanceof UriInterface)) { + if (!$uri instanceof UriInterface) { $uri = new Uri($uri); } diff --git a/lib/guzzlehttp/psr7/src/Uri.php b/lib/guzzlehttp/psr7/src/Uri.php index a7cdfb003..bef82e29d 100644 --- a/lib/guzzlehttp/psr7/src/Uri.php +++ b/lib/guzzlehttp/psr7/src/Uri.php @@ -51,7 +51,7 @@ class Uri implements UriInterface, \JsonSerializable * @see https://datatracker.ietf.org/doc/html/rfc3986#section-2.2 */ private const CHAR_SUB_DELIMS = '!\$&\'\(\)\*\+,;='; - private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26']; + private const QUERY_SEPARATORS_REPLACEMENT = ['=' => '%3D', '&' => '%26', '+' => '%2B']; /** @var string Uri scheme. */ private $scheme = ''; @@ -661,7 +661,8 @@ class Uri implements UriInterface, \JsonSerializable private static function generateQueryString(string $key, ?string $value): string { - // Query string separators ("=", "&") within the key or value need to be encoded + // Query string separators ("=", "&") and literal plus signs ("+") within the + // key or value need to be encoded // (while preventing double-encoding) before setting the query string. All other // chars that need percent-encoding will be encoded by withQuery(). $queryString = strtr($key, self::QUERY_SEPARATORS_REPLACEMENT); diff --git a/lib/league/oauth2-google/CHANGELOG.md b/lib/league/oauth2-google/CHANGELOG.md index d41761f51..c6436fed3 100644 --- a/lib/league/oauth2-google/CHANGELOG.md +++ b/lib/league/oauth2-google/CHANGELOG.md @@ -1,6 +1,12 @@ OAuth 2.0 Google Provider Changelog +## 4.2.0 - 2026-03-09 + +### Added + +- Allow `oauth2-client` version 2 or 3, #140 by @garak + ## 4.1.0 - 2025-12-15 ### Added diff --git a/lib/league/oauth2-google/composer.json b/lib/league/oauth2-google/composer.json index 73ce51ed8..6e698ee0a 100644 --- a/lib/league/oauth2-google/composer.json +++ b/lib/league/oauth2-google/composer.json @@ -20,7 +20,7 @@ "minimum-stability": "stable", "require": { "php": "^7.3 || ^8.0", - "league/oauth2-client": "^2.0" + "league/oauth2-client": "^2.0 || ^3.0" }, "require-dev": { "eloquent/phony-phpunit": "^6.0 || ^7.1", diff --git a/lib/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/lib/symfony/cache/Adapter/AbstractTagAwareAdapter.php index a1af6141b..0364bc2f6 100644 --- a/lib/symfony/cache/Adapter/AbstractTagAwareAdapter.php +++ b/lib/symfony/cache/Adapter/AbstractTagAwareAdapter.php @@ -192,8 +192,7 @@ abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagA if (\is_array($e) || 1 === \count($values)) { foreach (\is_array($e) ? $e : array_keys($values) as $id) { $ok = false; - $v = $values[$id]; - $type = get_debug_type($v); + $type = \array_key_exists($id, $values) ? get_debug_type($values[$id]) : 'unknown'; $message = \sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.'); CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null, 'cache-adapter' => get_debug_type($this)]); } diff --git a/lib/symfony/cache/Adapter/ArrayAdapter.php b/lib/symfony/cache/Adapter/ArrayAdapter.php index 38e19cbdd..87cd895b3 100644 --- a/lib/symfony/cache/Adapter/ArrayAdapter.php +++ b/lib/symfony/cache/Adapter/ArrayAdapter.php @@ -34,6 +34,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter private array $values = []; private array $tags = []; private array $expiries = []; + private array $explicitExpiries = []; private int $defaultLifetime; private float $maxLifetime; private int $maxItems; @@ -58,7 +59,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter $this->maxLifetime = $maxLifetime; $this->maxItems = $maxItems; self::$createCacheItem ??= \Closure::bind( - static function ($key, $value, $isHit, $tags) { + static function ($key, $value, $isHit, $tags, $expiry = null) { $item = new CacheItem(); $item->key = $key; $item->value = $value; @@ -66,6 +67,9 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter if (null !== $tags) { $item->metadata[CacheItem::METADATA_TAGS] = $tags; } + if (null !== $expiry) { + $item->metadata[CacheItem::METADATA_EXPIRY] = $expiry; + } return $item; }, @@ -126,7 +130,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key]; } - return (self::$createCacheItem)($key, $value, $isHit, $this->tags[$key] ?? null); + return (self::$createCacheItem)($key, $value, $isHit, $this->tags[$key] ?? null, $this->explicitExpiries[$key] ?? null); } public function getItems(array $keys = []): iterable @@ -139,7 +143,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter public function deleteItem(mixed $key): bool { \assert('' !== CacheItem::validateKey($key)); - unset($this->values[$key], $this->tags[$key], $this->expiries[$key]); + unset($this->values[$key], $this->tags[$key], $this->expiries[$key], $this->explicitExpiries[$key]); return true; } @@ -193,13 +197,19 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter break; } - unset($this->values[$k], $this->tags[$k], $this->expiries[$k]); + unset($this->values[$k], $this->tags[$k], $this->expiries[$k], $this->explicitExpiries[$k]); } } $this->values[$key] = $value; $this->expiries[$key] = $expiry ?? \PHP_INT_MAX; + if (null !== $item["\0*\0expiry"] && \PHP_INT_MAX !== $this->expiries[$key]) { + $this->explicitExpiries[$key] = $this->expiries[$key]; + } else { + unset($this->explicitExpiries[$key]); + } + if (null === $this->tags[$key] = $item["\0*\0newMetadata"][CacheItem::METADATA_TAGS] ?? null) { unset($this->tags[$key]); } @@ -224,7 +234,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter foreach ($this->values as $key => $value) { if (!isset($this->expiries[$key]) || $this->expiries[$key] <= $now || str_starts_with($key, $prefix)) { - unset($this->values[$key], $this->tags[$key], $this->expiries[$key]); + unset($this->values[$key], $this->tags[$key], $this->expiries[$key], $this->explicitExpiries[$key]); } } @@ -233,7 +243,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter } } - $this->values = $this->tags = $this->expiries = []; + $this->values = $this->tags = $this->expiries = $this->explicitExpiries = []; return true; } @@ -290,7 +300,7 @@ class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInter } unset($keys[$i]); - yield $key => $f($key, $value, $isHit, $this->tags[$key] ?? null); + yield $key => $f($key, $value, $isHit, $this->tags[$key] ?? null, $this->explicitExpiries[$key] ?? null); } foreach ($keys as $key) { diff --git a/lib/symfony/cache/Adapter/ChainAdapter.php b/lib/symfony/cache/Adapter/ChainAdapter.php index 1d187f65c..e240408a7 100644 --- a/lib/symfony/cache/Adapter/ChainAdapter.php +++ b/lib/symfony/cache/Adapter/ChainAdapter.php @@ -79,6 +79,7 @@ class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterfa $item->expiresAt(\DateTimeImmutable::createFromFormat('U.u', \sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY]))); } elseif (0 < $defaultLifetime) { $item->expiresAfter($defaultLifetime); + $item->newMetadata[CacheItem::METADATA_EXPIRY] = $item->expiry; } return $item; diff --git a/lib/symfony/cache/CacheItem.php b/lib/symfony/cache/CacheItem.php index 1aa5bcdce..e12e456b6 100644 --- a/lib/symfony/cache/CacheItem.php +++ b/lib/symfony/cache/CacheItem.php @@ -170,6 +170,10 @@ final class CacheItem implements ItemInterface } $valueWrapper = self::VALUE_WRAPPER; + if ($this->value instanceof $valueWrapper) { + return new $valueWrapper($this->value->value, $m + ['expiry' => $this->expiry] + $this->value->metadata); + } + return new $valueWrapper($this->value, $m + ['expiry' => $this->expiry]); } diff --git a/lib/symfony/cache/LockRegistry.php b/lib/symfony/cache/LockRegistry.php index 31ec51ced..545916b93 100644 --- a/lib/symfony/cache/LockRegistry.php +++ b/lib/symfony/cache/LockRegistry.php @@ -65,12 +65,14 @@ final class LockRegistry /** * Defines a set of existing files that will be used as keys to acquire locks. * - * @return array The previously defined set of files + * @param list $files A list of existing files + * + * @return list The previously defined set of files */ public static function setFiles(array $files): array { $previousFiles = self::$files; - self::$files = $files; + self::$files = array_values($files); foreach (self::$openedFiles as $file) { if ($file) { @@ -97,7 +99,7 @@ final class LockRegistry } self::$signalingException ??= unserialize("O:9:\"Exception\":1:{s:16:\"\0Exception\0trace\";a:0:{}}"); - self::$signalingCallback ??= fn () => throw self::$signalingException; + self::$signalingCallback ??= static fn () => throw self::$signalingException; while (true) { try { @@ -123,14 +125,33 @@ final class LockRegistry } // if we failed the race, retry locking in blocking mode to wait for the winner $logger?->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]); - flock($lock, \LOCK_SH); + + $deadline = microtime(true) + 30.0; + $acquired = false; + do { + if ($acquired = flock($lock, \LOCK_SH | \LOCK_NB)) { + break; + } + usleep(100_000); + } while (microtime(true) < $deadline); + + if (!$acquired) { + $logger?->warning('Lock on item "{key}" timed out, evicting slot', ['key' => $item->getKey()]); + unset(self::$files[$key]); + self::setFiles(self::$files); + $lock = null; + + return self::compute($callback, $item, $save, $pool, $setMetadata, $logger, $beta); + } if (\INF === $beta) { $logger?->info('Force-recomputing item "{key}"', ['key' => $item->getKey()]); continue; } } finally { - flock($lock, \LOCK_UN); + if ($lock) { + flock($lock, \LOCK_UN); + } unset(self::$lockedFiles[$key]); } diff --git a/lib/symfony/cache/Psr16Cache.php b/lib/symfony/cache/Psr16Cache.php index 01494d714..d5c65bc1d 100644 --- a/lib/symfony/cache/Psr16Cache.php +++ b/lib/symfony/cache/Psr16Cache.php @@ -18,6 +18,7 @@ use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Traits\ProxyTrait; +use Symfony\Contracts\Cache\ItemInterface; /** * Turns a PSR-6 cache into a PSR-16 one. @@ -68,6 +69,12 @@ class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterf }; self::$packCacheItem ??= \Closure::bind( static function (CacheItem $item) { + // Only re-pack if there's timing metadata (for Psr16Adapter compatibility) + // Don't re-pack if only tags metadata exists (TagAwareAdapter direct use case) + if (!isset($item->metadata[ItemInterface::METADATA_CTIME]) && !isset($item->metadata[ItemInterface::METADATA_EXPIRY])) { + return $item->value; + } + $item->newMetadata = $item->metadata; return $item->pack(); diff --git a/lib/symfony/cache/Traits/Relay/Relay21Trait.php b/lib/symfony/cache/Traits/Relay/Relay21Trait.php new file mode 100644 index 000000000..551e56343 --- /dev/null +++ b/lib/symfony/cache/Traits/Relay/Relay21Trait.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits\Relay; + +if (version_compare(phpversion('relay'), '0.21.0', '>=')) { + /** + * @internal + */ + trait Relay21Trait + { + public function gcra($key, $maxBurst, $requestsPerPeriod, $period, $numRequests = 0): \Relay\Relay|array|false + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->gcra(...\func_get_args()); + } + + public function hotkeys($subcmd, $args = null): \Relay\Relay|array|bool + { + return ($this->lazyObjectState->realInstance ??= ($this->lazyObjectState->initializer)())->hotkeys(...\func_get_args()); + } + } +} else { + /** + * @internal + */ + trait Relay21Trait + { + } +} diff --git a/lib/symfony/cache/Traits/RelayProxy.php b/lib/symfony/cache/Traits/RelayProxy.php index 8933e93ac..5deaac09c 100644 --- a/lib/symfony/cache/Traits/RelayProxy.php +++ b/lib/symfony/cache/Traits/RelayProxy.php @@ -26,6 +26,7 @@ use Symfony\Component\Cache\Traits\Relay\Relay11Trait; use Symfony\Component\Cache\Traits\Relay\Relay121Trait; use Symfony\Component\Cache\Traits\Relay\Relay12Trait; use Symfony\Component\Cache\Traits\Relay\Relay20Trait; +use Symfony\Component\Cache\Traits\Relay\Relay21Trait; use Symfony\Component\Cache\Traits\Relay\SwapdbTrait; use Symfony\Component\VarExporter\LazyObjectInterface; use Symfony\Component\VarExporter\LazyProxyTrait; @@ -60,6 +61,7 @@ class RelayProxy extends \Relay\Relay implements ResetInterface, LazyObjectInter use Relay12Trait; use Relay121Trait; use Relay20Trait; + use Relay21Trait; use SwapdbTrait; private const LAZY_OBJECT_PROPERTY_SCOPES = []; diff --git a/lib/symfony/console/Formatter/OutputFormatter.php b/lib/symfony/console/Formatter/OutputFormatter.php index a30e44d84..d60365f84 100644 --- a/lib/symfony/console/Formatter/OutputFormatter.php +++ b/lib/symfony/console/Formatter/OutputFormatter.php @@ -133,6 +133,10 @@ class OutputFormatter implements WrappableOutputFormatterInterface return ''; } + // For ASCII-only strings, byte positions equal character positions, + // so we can use native strlen/substr which is much faster than Helper::length/substr. + $isAscii = !preg_match('/[\x80-\xFF]/', $message); + $offset = 0; $output = ''; $openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*'; @@ -147,11 +151,17 @@ class OutputFormatter implements WrappableOutputFormatterInterface continue; } - // convert byte position to character position. - $pos = Helper::length(substr($message, 0, $pos)); - // add the text up to the next tag - $output .= $this->applyCurrentStyle(Helper::substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); - $offset = $pos + Helper::length($text); + if ($isAscii) { + // For ASCII, byte position = character position, no conversion needed + $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); + $offset = $pos + \strlen($text); + } else { + // convert byte position to character position. + $pos = Helper::length(substr($message, 0, $pos)); + // add the text up to the next tag + $output .= $this->applyCurrentStyle(Helper::substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength); + $offset = $pos + Helper::length($text); + } // opening tag? if ($open = '/' !== $text[1]) { @@ -172,7 +182,7 @@ class OutputFormatter implements WrappableOutputFormatterInterface } } - $output .= $this->applyCurrentStyle(Helper::substr($message, $offset), $output, $width, $currentLineLength); + $output .= $this->applyCurrentStyle($isAscii ? substr($message, $offset) : Helper::substr($message, $offset), $output, $width, $currentLineLength); return strtr($output, ["\0" => '\\', '\\<' => '<', '\\>' => '>']); } diff --git a/lib/symfony/console/Output/ConsoleOutput.php b/lib/symfony/console/Output/ConsoleOutput.php index 5837e74a3..1e4910178 100644 --- a/lib/symfony/console/Output/ConsoleOutput.php +++ b/lib/symfony/console/Output/ConsoleOutput.php @@ -142,12 +142,27 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface */ private function openOutputStream() { + static $stdout; + + if ($stdout) { + return $stdout; + } + if (!$this->hasStdoutSupport()) { - return fopen('php://output', 'w'); + return $stdout = fopen('php://output', 'w'); } // Use STDOUT when possible to prevent from opening too many file descriptors - return \defined('STDOUT') ? \STDOUT : (@fopen('php://stdout', 'w') ?: fopen('php://output', 'w')); + if (!\defined('STDOUT')) { + return $stdout = @fopen('php://stdout', 'w') ?: fopen('php://output', 'w'); + } + + // On Windows, STDOUT is opened in text mode; reopen in binary mode to prevent \n to \r\n conversion + if ('\\' === \DIRECTORY_SEPARATOR) { + return $stdout = @fopen('php://stdout', 'w') ?: \STDOUT; + } + + return $stdout = \STDOUT; } /** @@ -155,11 +170,26 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface */ private function openErrorStream() { + static $stderr; + + if ($stderr) { + return $stderr; + } + if (!$this->hasStderrSupport()) { - return fopen('php://output', 'w'); + return $stderr = fopen('php://output', 'w'); } // Use STDERR when possible to prevent from opening too many file descriptors - return \defined('STDERR') ? \STDERR : (@fopen('php://stderr', 'w') ?: fopen('php://output', 'w')); + if (!\defined('STDERR')) { + return $stderr = @fopen('php://stderr', 'w') ?: fopen('php://output', 'w'); + } + + // On Windows, STDERR is opened in text mode; reopen in binary mode to prevent \n → \r\n conversion + if ('\\' === \DIRECTORY_SEPARATOR) { + return $stderr = @fopen('php://stderr', 'w') ?: \STDERR; + } + + return $stderr ??= \STDERR; } } diff --git a/lib/symfony/console/Tester/ApplicationTester.php b/lib/symfony/console/Tester/ApplicationTester.php index 58aee54d6..dfb04a189 100644 --- a/lib/symfony/console/Tester/ApplicationTester.php +++ b/lib/symfony/console/Tester/ApplicationTester.php @@ -49,7 +49,7 @@ class ApplicationTester */ public function run(array $input, array $options = []): int { - $prevShellVerbosity = getenv('SHELL_VERBOSITY'); + $prevShellVerbosity = [getenv('SHELL_VERBOSITY'), $_ENV['SHELL_VERBOSITY'] ?? false, $_SERVER['SHELL_VERBOSITY'] ?? false]; try { $this->input = new ArrayInput($input); @@ -63,22 +63,35 @@ class ApplicationTester $this->initOutput($options); + // Temporarily clear SHELL_VERBOSITY to prevent Application::configureIO + // from overriding the interactive and verbosity settings set above + if (\function_exists('putenv')) { + @putenv('SHELL_VERBOSITY'); + } + unset($_ENV['SHELL_VERBOSITY'], $_SERVER['SHELL_VERBOSITY']); + return $this->statusCode = $this->application->run($this->input, $this->output); } finally { // SHELL_VERBOSITY is set by Application::configureIO so we need to unset/reset it // to its previous value to avoid one test's verbosity to spread to the following tests - if (false === $prevShellVerbosity) { + if (false === $prevShellVerbosity[0]) { if (\function_exists('putenv')) { @putenv('SHELL_VERBOSITY'); } - unset($_ENV['SHELL_VERBOSITY']); - unset($_SERVER['SHELL_VERBOSITY']); } else { if (\function_exists('putenv')) { - @putenv('SHELL_VERBOSITY='.$prevShellVerbosity); + @putenv('SHELL_VERBOSITY='.$prevShellVerbosity[0]); } - $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity; - $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity; + } + if (false === $prevShellVerbosity[1]) { + unset($_ENV['SHELL_VERBOSITY']); + } else { + $_ENV['SHELL_VERBOSITY'] = $prevShellVerbosity[1]; + } + if (false === $prevShellVerbosity[2]) { + unset($_SERVER['SHELL_VERBOSITY']); + } else { + $_SERVER['SHELL_VERBOSITY'] = $prevShellVerbosity[2]; } } } diff --git a/lib/symfony/debug-bundle/CHANGELOG.md b/lib/symfony/debug-bundle/CHANGELOG.md new file mode 100644 index 000000000..685dd1d07 --- /dev/null +++ b/lib/symfony/debug-bundle/CHANGELOG.md @@ -0,0 +1,8 @@ +CHANGELOG +========= + +4.1.0 +----- + + * Added the `server:dump` command to run a server collecting and displaying + dumps on a single place with multiple formats support diff --git a/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php b/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php new file mode 100644 index 000000000..69ee83d18 --- /dev/null +++ b/lib/symfony/debug-bundle/Command/ServerDumpPlaceholderCommand.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle\Command; + +use Symfony\Component\Console\Attribute\AsCommand; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\VarDumper\Command\ServerDumpCommand; +use Symfony\Component\VarDumper\Server\DumpServer; + +/** + * A placeholder command easing VarDumper server discovery. + * + * @author Maxime Steinhausser + * + * @internal + */ +#[AsCommand(name: 'server:dump', description: 'Start a dump server that collects and displays dumps in a single place')] +class ServerDumpPlaceholderCommand extends Command +{ + private ServerDumpCommand $replacedCommand; + + public function __construct(?DumpServer $server = null, array $descriptors = []) + { + $this->replacedCommand = new ServerDumpCommand((new \ReflectionClass(DumpServer::class))->newInstanceWithoutConstructor(), $descriptors); + + parent::__construct(); + } + + protected function configure(): void + { + $this->setDefinition($this->replacedCommand->getDefinition()); + $this->setHelp($this->replacedCommand->getHelp()); + $this->setDescription($this->replacedCommand->getDescription()); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + (new SymfonyStyle($input, $output))->getErrorStyle()->warning('In order to use the VarDumper server, set the "debug.dump_destination" config option to "tcp://%env(VAR_DUMPER_SERVER)%"'); + + return 8; + } +} diff --git a/lib/symfony/debug-bundle/DebugBundle.php b/lib/symfony/debug-bundle/DebugBundle.php new file mode 100644 index 000000000..0af84fb5a --- /dev/null +++ b/lib/symfony/debug-bundle/DebugBundle.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle; + +use Symfony\Bundle\DebugBundle\DependencyInjection\Compiler\DumpDataCollectorPass; +use Symfony\Component\Console\Application; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\Bundle\Bundle; +use Symfony\Component\VarDumper\VarDumper; + +/** + * @author Nicolas Grekas + */ +class DebugBundle extends Bundle +{ + /** + * @return void + */ + public function boot() + { + if ($this->container->getParameter('kernel.debug')) { + $container = $this->container; + + // This code is here to lazy load the dump stack. This default + // configuration is overridden in CLI mode on 'console.command' event. + // 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) { + $dumper = $container->get('data_collector.dump'); + $cloner = $container->get('var_dumper.cloner'); + $handler = function ($var, ?string $label = null) use ($dumper, $cloner) { + $var = $cloner->cloneVar($var); + if (null !== $label) { + $var = $var->withContext(['label' => $label]); + } + + $dumper->dump($var); + }; + VarDumper::setHandler($handler); + $handler($var, $label); + }); + } + } + + /** + * @return void + */ + public function build(ContainerBuilder $container) + { + parent::build($container); + + $container->addCompilerPass(new DumpDataCollectorPass()); + } + + /** + * @return void + */ + public function registerCommands(Application $application) + { + // noop + } +} diff --git a/lib/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php b/lib/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php new file mode 100644 index 000000000..3d0b27380 --- /dev/null +++ b/lib/symfony/debug-bundle/DependencyInjection/Compiler/DumpDataCollectorPass.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle\DependencyInjection\Compiler; + +use Symfony\Bundle\WebProfilerBundle\EventListener\WebDebugToolbarListener; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Registers the file link format for the {@link \Symfony\Component\HttpKernel\DataCollector\DumpDataCollector}. + * + * @author Christian Flothmann + */ +class DumpDataCollectorPass implements CompilerPassInterface +{ + /** + * @return void + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('data_collector.dump')) { + return; + } + + $definition = $container->getDefinition('data_collector.dump'); + + if (!$container->has('.virtual_request_stack')) { + $definition->replaceArgument(3, new Reference('request_stack')); + } + + if (!$container->hasParameter('web_profiler.debug_toolbar.mode') || WebDebugToolbarListener::DISABLED === $container->getParameter('web_profiler.debug_toolbar.mode')) { + $definition->replaceArgument(3, null); + } + + if (!$container->hasParameter('kernel.runtime_mode.web')) { + $definition->replaceArgument(5, null); + } + } +} diff --git a/lib/symfony/debug-bundle/DependencyInjection/Configuration.php b/lib/symfony/debug-bundle/DependencyInjection/Configuration.php new file mode 100644 index 000000000..caf735969 --- /dev/null +++ b/lib/symfony/debug-bundle/DependencyInjection/Configuration.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle\DependencyInjection; + +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; + +/** + * DebugExtension configuration structure. + * + * @author Nicolas Grekas + */ +class Configuration implements ConfigurationInterface +{ + public function getConfigTreeBuilder(): TreeBuilder + { + $treeBuilder = new TreeBuilder('debug'); + + $rootNode = $treeBuilder->getRootNode(); + $rootNode->children() + ->integerNode('max_items') + ->info('Max number of displayed items past the first level, -1 means no limit') + ->min(-1) + ->defaultValue(2500) + ->end() + ->integerNode('min_depth') + ->info('Minimum tree depth to clone all the items, 1 is default') + ->min(0) + ->defaultValue(1) + ->end() + ->integerNode('max_string_length') + ->info('Max length of displayed strings, -1 means no limit') + ->min(-1) + ->defaultValue(-1) + ->end() + ->scalarNode('dump_destination') + ->info('A stream URL where dumps should be written to') + ->example('php://stderr, or tcp://%env(VAR_DUMPER_SERVER)% when using the "server:dump" command') + ->defaultNull() + ->end() + ->enumNode('theme') + ->info('Changes the color of the dump() output when rendered directly on the templating. "dark" (default) or "light"') + ->example('dark') + ->values(['dark', 'light']) + ->defaultValue('dark') + ->end() + ; + + return $treeBuilder; + } +} diff --git a/lib/symfony/debug-bundle/DependencyInjection/DebugExtension.php b/lib/symfony/debug-bundle/DependencyInjection/DebugExtension.php new file mode 100644 index 000000000..d00d6111c --- /dev/null +++ b/lib/symfony/debug-bundle/DependencyInjection/DebugExtension.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\DebugBundle\DependencyInjection; + +use Symfony\Bridge\Monolog\Command\ServerLogCommand; +use Symfony\Bundle\DebugBundle\Command\ServerDumpPlaceholderCommand; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\VarDumper\Caster\ReflectionCaster; + +/** + * DebugExtension. + * + * @author Nicolas Grekas + */ +class DebugExtension extends Extension +{ + /** + * @return void + */ + public function load(array $configs, ContainerBuilder $container) + { + $configuration = new Configuration(); + $config = $this->processConfiguration($configuration, $configs); + + $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.php'); + + $container->getDefinition('var_dumper.cloner') + ->addMethodCall('setMaxItems', [$config['max_items']]) + ->addMethodCall('setMinDepth', [$config['min_depth']]) + ->addMethodCall('setMaxString', [$config['max_string_length']]) + ->addMethodCall('addCasters', [ReflectionCaster::UNSET_CLOSURE_FILE_INFO]); + + if ('dark' !== $config['theme']) { + $container->getDefinition('var_dumper.html_dumper') + ->addMethodCall('setTheme', [$config['theme']]); + } + + if (null === $config['dump_destination']) { + $container->getDefinition('var_dumper.command.server_dump') + ->setClass(ServerDumpPlaceholderCommand::class) + ; + } elseif (str_starts_with($config['dump_destination'], 'tcp://')) { + $container->getDefinition('debug.dump_listener') + ->replaceArgument(2, new Reference('var_dumper.server_connection')) + ; + $container->getDefinition('data_collector.dump') + ->replaceArgument(4, new Reference('var_dumper.server_connection')) + ; + $container->getDefinition('var_dumper.dump_server') + ->replaceArgument(0, $config['dump_destination']) + ; + $container->getDefinition('var_dumper.server_connection') + ->replaceArgument(0, $config['dump_destination']) + ; + } else { + $container->getDefinition('var_dumper.cli_dumper') + ->replaceArgument(0, $config['dump_destination']) + ; + $container->getDefinition('data_collector.dump') + ->replaceArgument(4, new Reference('var_dumper.cli_dumper')) + ; + $container->getDefinition('var_dumper.command.server_dump') + ->setClass(ServerDumpPlaceholderCommand::class) + ; + } + + $container->getDefinition('var_dumper.cli_dumper') + ->addMethodCall('setDisplayOptions', [[ + 'fileLinkFormat' => new Reference('debug.file_link_formatter', ContainerBuilder::IGNORE_ON_INVALID_REFERENCE), + ]]) + ; + + if (!class_exists(Command::class) || !class_exists(ServerLogCommand::class)) { + $container->removeDefinition('monolog.command.server_log'); + } + } + + public function getXsdValidationBasePath(): string|false + { + return __DIR__.'/../Resources/config/schema'; + } + + public function getNamespace(): string + { + return 'http://symfony.com/schema/dic/debug'; + } +} diff --git a/lib/symfony/debug-bundle/LICENSE b/lib/symfony/debug-bundle/LICENSE new file mode 100644 index 000000000..29f72d5e9 --- /dev/null +++ b/lib/symfony/debug-bundle/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/symfony/debug-bundle/README.md b/lib/symfony/debug-bundle/README.md new file mode 100644 index 000000000..bed2f5b6d --- /dev/null +++ b/lib/symfony/debug-bundle/README.md @@ -0,0 +1,13 @@ +DebugBundle +=========== + +DebugBundle provides a tight integration of the Symfony VarDumper component and +the ServerLogCommand from MonologBridge into the Symfony full-stack framework. + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/debug-bundle/Resources/config/schema/debug-1.0.xsd b/lib/symfony/debug-bundle/Resources/config/schema/debug-1.0.xsd new file mode 100644 index 000000000..323068860 --- /dev/null +++ b/lib/symfony/debug-bundle/Resources/config/schema/debug-1.0.xsd @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/lib/symfony/debug-bundle/Resources/config/services.php b/lib/symfony/debug-bundle/Resources/config/services.php new file mode 100644 index 000000000..0193f65a2 --- /dev/null +++ b/lib/symfony/debug-bundle/Resources/config/services.php @@ -0,0 +1,141 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Monolog\Formatter\FormatterInterface; +use Symfony\Bridge\Monolog\Command\ServerLogCommand; +use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; +use Symfony\Bridge\Twig\Extension\DumpExtension; +use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector; +use Symfony\Component\HttpKernel\EventListener\DumpListener; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Command\Descriptor\CliDescriptor; +use Symfony\Component\VarDumper\Command\Descriptor\HtmlDescriptor; +use Symfony\Component\VarDumper\Command\ServerDumpCommand; +use Symfony\Component\VarDumper\Dumper\CliDumper; +use Symfony\Component\VarDumper\Dumper\ContextProvider\CliContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextProvider\RequestContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; +use Symfony\Component\VarDumper\Dumper\ContextualizedDumper; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\Server\Connection; +use Symfony\Component\VarDumper\Server\DumpServer; + +return static function (ContainerConfigurator $container) { + $container->parameters() + ->set('env(VAR_DUMPER_SERVER)', '127.0.0.1:9912') + ; + + $container->services() + + ->set('twig.extension.dump', DumpExtension::class) + ->args([ + service('var_dumper.cloner'), + service('var_dumper.html_dumper'), + ]) + ->tag('twig.extension') + + ->set('data_collector.dump', DumpDataCollector::class) + ->public() + ->args([ + service('debug.stopwatch')->ignoreOnInvalid(), + service('debug.file_link_formatter')->ignoreOnInvalid(), + param('kernel.charset'), + service('.virtual_request_stack'), + null, // var_dumper.cli_dumper or var_dumper.server_connection when debug.dump_destination is set + param('kernel.runtime_mode.web'), + ]) + ->tag('data_collector', [ + 'id' => 'dump', + 'template' => '@Debug/Profiler/dump.html.twig', + 'priority' => 240, + ]) + + ->set('debug.dump_listener', DumpListener::class) + ->args([ + service('var_dumper.cloner'), + service('var_dumper.cli_dumper'), + null, + ]) + ->tag('kernel.event_subscriber') + + ->set('var_dumper.cloner', VarCloner::class) + ->public() + + ->set('var_dumper.cli_dumper', CliDumper::class) + ->args([ + null, // debug.dump_destination, + param('kernel.charset'), + 0, // flags + ]) + + ->set('var_dumper.contextualized_cli_dumper', ContextualizedDumper::class) + ->decorate('var_dumper.cli_dumper') + ->args([ + service('var_dumper.contextualized_cli_dumper.inner'), + [ + 'source' => inline_service(SourceContextProvider::class)->args([ + param('kernel.charset'), + param('kernel.project_dir'), + service('debug.file_link_formatter')->nullOnInvalid(), + ]), + ], + ]) + + ->set('var_dumper.html_dumper', HtmlDumper::class) + ->args([ + null, + param('kernel.charset'), + 0, // flags + ]) + ->call('setDisplayOptions', [ + ['fileLinkFormat' => service('debug.file_link_formatter')->ignoreOnInvalid()], + ]) + + ->set('var_dumper.server_connection', Connection::class) + ->args([ + '', // server host + [ + 'source' => inline_service(SourceContextProvider::class)->args([ + param('kernel.charset'), + param('kernel.project_dir'), + service('debug.file_link_formatter')->nullOnInvalid(), + ]), + 'request' => inline_service(RequestContextProvider::class)->args([service('request_stack')]), + 'cli' => inline_service(CliContextProvider::class), + ], + ]) + + ->set('var_dumper.dump_server', DumpServer::class) + ->args([ + '', // server host + service('logger')->nullOnInvalid(), + ]) + ->tag('monolog.logger', ['channel' => 'debug']) + + ->set('var_dumper.command.server_dump', ServerDumpCommand::class) + ->args([ + service('var_dumper.dump_server'), + [ + 'cli' => inline_service(CliDescriptor::class)->args([service('var_dumper.contextualized_cli_dumper.inner')]), + 'html' => inline_service(HtmlDescriptor::class)->args([service('var_dumper.html_dumper')]), + ], + ]) + ->tag('console.command') + + ->set('monolog.command.server_log', ServerLogCommand::class) + ; + + if (class_exists(ConsoleFormatter::class) && interface_exists(FormatterInterface::class)) { + $container->services()->get('monolog.command.server_log')->tag('console.command'); + } +}; diff --git a/lib/symfony/debug-bundle/Resources/views/Profiler/dump.html.twig b/lib/symfony/debug-bundle/Resources/views/Profiler/dump.html.twig new file mode 100644 index 000000000..e98e52474 --- /dev/null +++ b/lib/symfony/debug-bundle/Resources/views/Profiler/dump.html.twig @@ -0,0 +1,83 @@ +{% extends '@WebProfiler/Profiler/layout.html.twig' %} + +{% block toolbar %} + {% if collector.dumpsCount %} + {% set icon %} + {{ source('@Debug/Profiler/icon.svg') }} + {{ collector.dumpsCount }} + {% endset %} + + {% set text %} + {% for dump in collector.getDumps('html') %} +
+ + {% if dump.label is defined and '' != dump.label %} + {{ dump.label }} in + {% endif %} + {% if dump.file %} + {% set link = dump.file|file_link(dump.line) %} + {% if link %} + {{ dump.name }} + {% else %} + {{ dump.name }} + {% endif %} + {% else %} + {{ dump.name }} + {% endif %} + + line {{ dump.line }} + + {{ dump.data|raw }} +
+ {% endfor %} + {% endset %} + + {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }} + {% endif %} +{% endblock %} + +{% block menu %} + + {{ source('@Debug/Profiler/icon.svg') }} + Debug + +{% endblock %} + +{% block panel %} +

Dumped Contents

+ + {% for dump in collector.getDumps('html') %} +
+ + + + + {{ dump.data|raw }} +
+ {% else %} +
+

No content was dumped.

+
+ {% endfor %} +{% endblock %} diff --git a/lib/symfony/debug-bundle/Resources/views/Profiler/icon.svg b/lib/symfony/debug-bundle/Resources/views/Profiler/icon.svg new file mode 100644 index 000000000..9ba3a7d94 --- /dev/null +++ b/lib/symfony/debug-bundle/Resources/views/Profiler/icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/lib/symfony/debug-bundle/composer.json b/lib/symfony/debug-bundle/composer.json new file mode 100644 index 000000000..1d058228f --- /dev/null +++ b/lib/symfony/debug-bundle/composer.json @@ -0,0 +1,41 @@ +{ + "name": "symfony/debug-bundle", + "type": "symfony-bundle", + "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1", + "ext-xml": "*", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/twig-bridge": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "require-dev": { + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/dependency-injection": "<5.4" + }, + "autoload": { + "psr-4": { "Symfony\\Bundle\\DebugBundle\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/lib/symfony/dependency-injection/Dumper/PhpDumper.php b/lib/symfony/dependency-injection/Dumper/PhpDumper.php index 1f9f4d31f..2fe6a6f0e 100644 --- a/lib/symfony/dependency-injection/Dumper/PhpDumper.php +++ b/lib/symfony/dependency-injection/Dumper/PhpDumper.php @@ -1295,16 +1295,9 @@ EOF; } } - if (Container::class !== $this->baseClass) { - $r = $this->container->getReflectionClass($this->baseClass, false); - if (null !== $r - && (null !== $constructor = $r->getConstructor()) - && 0 === $constructor->getNumberOfRequiredParameters() - && Container::class !== $constructor->getDeclaringClass()->name - ) { - $code .= " parent::__construct();\n"; - $code .= " \$this->parameterBag = null;\n\n"; - } + if ($this->needsUnsetParameterBag()) { + $code .= " parent::__construct();\n"; + $code .= " unset(\$this->parameterBag);\n\n"; } if ($this->container->getParameterBag()->all()) { @@ -1582,9 +1575,22 @@ EOF; return $code ? \sprintf("\n \$this->privates['service_container'] = static function (\$container) {%s\n };\n", $code) : ''; } + private function needsUnsetParameterBag(): bool + { + if (Container::class === $this->baseClass) { + return false; + } + $r = $this->container->getReflectionClass($this->baseClass, false); + + return null !== $r + && (null !== $constructor = $r->getConstructor()) + && 0 === $constructor->getNumberOfRequiredParameters() + && Container::class !== $constructor->getDeclaringClass()->name; + } + private function addDefaultParametersMethod(): string { - if (!$this->container->getParameterBag()->all()) { + if (!$this->container->getParameterBag()->all() && !$this->needsUnsetParameterBag()) { return ''; } diff --git a/lib/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php b/lib/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php index d96eacb6d..f1a1bc07b 100644 --- a/lib/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php +++ b/lib/symfony/dependency-injection/Loader/Configurator/AbstractConfigurator.php @@ -77,6 +77,18 @@ abstract class AbstractConfigurator $value = (self::$valuePreProcessor)($value, $allowServices); } + if ($value instanceof ParamConfigurator) { + return (string) $value; + } + + if (\is_scalar($value ?? '') || $value instanceof \UnitEnum) { + return $value; + } + + if (!$allowServices) { + throw new InvalidArgumentException(\sprintf('Cannot use values of type "%s" in service configuration files.', get_debug_type($value))); + } + if ($value instanceof ReferenceConfigurator) { $reference = new Reference($value->id, $value->invalidBehavior); @@ -90,29 +102,18 @@ abstract class AbstractConfigurator return $def; } - if ($value instanceof ParamConfigurator) { - return (string) $value; - } - if ($value instanceof self) { throw new InvalidArgumentException(\sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY)); } switch (true) { - case null === $value: - case \is_scalar($value): - case $value instanceof \UnitEnum: - return $value; - case $value instanceof ArgumentInterface: case $value instanceof Definition: case $value instanceof Expression: case $value instanceof Parameter: case $value instanceof AbstractArgument: case $value instanceof Reference: - if ($allowServices) { - return $value; - } + return $value; } throw new InvalidArgumentException(\sprintf('Cannot use values of type "%s" in service configuration files.', get_debug_type($value))); diff --git a/lib/symfony/dotenv/Dotenv.php b/lib/symfony/dotenv/Dotenv.php index 2d726285f..fa1965054 100644 --- a/lib/symfony/dotenv/Dotenv.php +++ b/lib/symfony/dotenv/Dotenv.php @@ -14,6 +14,7 @@ namespace Symfony\Component\Dotenv; use Symfony\Component\Dotenv\Exception\FormatException; use Symfony\Component\Dotenv\Exception\FormatExceptionContext; use Symfony\Component\Dotenv\Exception\PathException; +use Symfony\Component\Dotenv\Exception\VariableCircularReferenceException; use Symfony\Component\Process\Exception\ExceptionInterface as ProcessException; use Symfony\Component\Process\Process; @@ -81,6 +82,7 @@ final class Dotenv public function load(string $path, string ...$extraPaths): void { $this->doLoad(false, \func_get_args()); + $this->resolveLoadedVars(); } /** @@ -100,33 +102,42 @@ final class Dotenv */ public function loadEnv(string $path, ?string $envKey = null, string $defaultEnv = 'dev', array $testEnvs = ['test'], bool $overrideExistingVars = false): void { - $k = $envKey ?? $this->envKey; + try { + $k = $envKey ?? $this->envKey; - if (is_file($path) || !is_file($p = "$path.dist")) { - $this->doLoad($overrideExistingVars, [$path]); - } else { - $this->doLoad($overrideExistingVars, [$p]); - } + if (is_file($path) || !is_file($p = "$path.dist")) { + $this->doLoad($overrideExistingVars, [$path]); + } else { + $this->doLoad($overrideExistingVars, [$p]); + } - if (null === $env = $_SERVER[$k] ?? $_ENV[$k] ?? null) { - $this->populate([$k => $env = $defaultEnv], $overrideExistingVars); - } + if (null === $env = $_SERVER[$k] ?? $_ENV[$k] ?? null) { + $this->populate([$k => $env = $defaultEnv], $overrideExistingVars); + } elseif (str_contains($env, '$') || str_contains($env, "\x00") || str_contains($env, '\\')) { + $env = $this->resolveEnvKey($env, $k); + } - if (!\in_array($env, $testEnvs, true) && is_file($p = "$path.local")) { - $this->doLoad($overrideExistingVars, [$p]); - $env = $_SERVER[$k] ?? $_ENV[$k] ?? $env; - } + if (!\in_array($env, $testEnvs, true) && is_file($p = "$path.local")) { + $this->doLoad($overrideExistingVars, [$p]); + $env = $_SERVER[$k] ?? $_ENV[$k] ?? $env; + if (str_contains($env, '$') || str_contains($env, "\x00") || str_contains($env, '\\')) { + $env = $this->resolveEnvKey($env, $k); + } + } - if ('local' === $env) { - return; - } + if ('local' === $env) { + return; + } - if (is_file($p = "$path.$env")) { - $this->doLoad($overrideExistingVars, [$p]); - } + if (is_file($p = "$path.$env")) { + $this->doLoad($overrideExistingVars, [$p]); + } - if (is_file($p = "$path.$env.local")) { - $this->doLoad($overrideExistingVars, [$p]); + if (is_file($p = "$path.$env.local")) { + $this->doLoad($overrideExistingVars, [$p]); + } + } finally { + $this->resolveLoadedVars(); } } @@ -168,6 +179,7 @@ final class Dotenv public function overload(string $path, string ...$extraPaths): void { $this->doLoad(true, \func_get_args()); + $this->resolveLoadedVars(); } /** @@ -236,6 +248,48 @@ final class Dotenv $this->values = []; $name = ''; + $loadedVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '')); + unset($loadedVars['']); + + $this->skipEmptyLines(); + + while ($this->cursor < $this->end) { + switch ($state) { + case self::STATE_VARNAME: + $name = $this->lexVarname(); + $state = self::STATE_VALUE; + break; + + case self::STATE_VALUE: + $this->values[$name] = $this->resolveValue($this->lexValue(), $loadedVars); + $state = self::STATE_VARNAME; + break; + } + } + + if (self::STATE_VALUE === $state) { + $this->values[$name] = ''; + } + + try { + return $this->values; + } finally { + $this->values = []; + unset($this->path, $this->cursor, $this->lineno, $this->data, $this->end); + } + } + + private function parseRaw(string $data, string $path = '.env'): array + { + $this->path = $path; + $this->data = str_replace(["\r\n", "\r"], "\n", $data); + $this->lineno = 1; + $this->cursor = 0; + $this->end = \strlen($this->data); + $state = self::STATE_VARNAME; + $this->values = []; + $name = ''; + $this->skipEmptyLines(); while ($this->cursor < $this->end) { @@ -260,10 +314,22 @@ final class Dotenv return $this->values; } finally { $this->values = []; - unset($this->path, $this->cursor, $this->lineno, $this->data, $this->end); } } + /** + * Resolves a raw value by expanding commands, variables, backslash escapes, + * and restoring literal $ markers. + */ + private function resolveValue(string $value, array $loadedVars): string + { + $resolved = $this->resolveCommands($value, $loadedVars); + $resolved = $this->resolveVariables($resolved, $loadedVars); + $resolved = str_replace('\\\\', '\\', $resolved); + + return str_replace("\x00", '$', $resolved); + } + private function lexVarname(): string { // var name + optional export @@ -305,8 +371,6 @@ final class Dotenv throw $this->createFormatException('Whitespace are not supported before the value'); } - $loadedVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '')); - unset($loadedVars['']); $v = ''; do { @@ -321,7 +385,10 @@ final class Dotenv } } while ("'" !== $this->data[$this->cursor + $len]); - $v .= substr($this->data, 1 + $this->cursor, $len - 1); + // In single-quoted strings, $ is literal and \ has no special meaning. + // Double backslashes so they survive the unescape in resolveValue(), + // and mark $ as \x00 so it's not treated as a variable reference. + $v .= str_replace(['\\', '$'], ['\\\\', "\x00"], substr($this->data, 1 + $this->cursor, $len - 1)); $this->cursor += 1 + $len; } elseif ('"' === $this->data[$this->cursor]) { $value = ''; @@ -340,11 +407,8 @@ final class Dotenv } ++$this->cursor; $value = str_replace(['\\"', '\r', '\n'], ['"', "\r", "\n"], $value); - $resolvedValue = $value; - $resolvedValue = $this->resolveCommands($resolvedValue, $loadedVars); - $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); - $resolvedValue = str_replace('\\\\', '\\', $resolvedValue); - $v .= $resolvedValue; + // Mark escaped $ (\$) as \x00 so it's treated as literal + $v .= $this->protectEscapedDollars($value); } else { $value = ''; $prevChr = $this->data[$this->cursor - 1]; @@ -363,12 +427,9 @@ final class Dotenv ++$this->cursor; } $value = rtrim($value); - $resolvedValue = $value; - $resolvedValue = $this->resolveCommands($resolvedValue, $loadedVars); - $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); - $resolvedValue = str_replace('\\\\', '\\', $resolvedValue); + $resolvedValue = $this->protectEscapedDollars($value); - if ($resolvedValue === $value && preg_match('/\s+/', $value)) { + if ($resolvedValue === $value && preg_match('/\s+/', $value) && !str_contains($value, '$')) { throw $this->createFormatException('A value containing spaces must be surrounded by quotes'); } @@ -385,6 +446,26 @@ final class Dotenv return $v; } + /** + * Converts \$ (escaped dollar) to \x00 (literal marker), handling + * even/odd backslash counts correctly: \$ → \x00, \\$ → \\$ (unchanged). + */ + private function protectEscapedDollars(string $value): string + { + if (!str_contains($value, '$')) { + return $value; + } + + return preg_replace_callback('/\\\\+\$/', static function ($m) { + $bs = substr($m[0], 0, -1); + if (1 === \strlen($bs) % 2) { + return substr($bs, 0, -1)."\x00"; + } + + return $m[0]; + }, $value); + } + private function lexNestedExpression(): string { ++$this->cursor; @@ -559,7 +640,148 @@ final class Dotenv 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); + if (str_contains($data, "\0")) { + throw new FormatException('Loading files containing NUL bytes is not supported.', new FormatExceptionContext($data, $path, 1, 0)); + } + + $this->populate($this->parseRaw($data, $path), $overrideExistingVars); } } + + /** + * Eagerly resolves a raw env key value so that loadEnv() can determine + * which additional .env files to load before full deferred resolution. + */ + private function resolveEnvKey(string $value, string $name): string + { + $loadedVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '')); + unset($loadedVars['']); + + // Save and clear own value so self-referencing defaults work + $envBackup = $_ENV[$name] ?? null; + $serverBackup = $_SERVER[$name] ?? null; + unset($_ENV[$name], $_SERVER[$name]); + if ($this->usePutenv) { + $getenvBackup = (string) getenv($name); + putenv($name); + } + + $this->values = []; + $this->path = ''; + $this->data = ''; + $this->lineno = 0; + $this->cursor = 0; + $this->end = 0; + + $resolved = $this->resolveCommands($value, $loadedVars); + $resolved = $this->resolveVariables($resolved, $loadedVars); + $resolved = str_replace(["\x00", '\\\\'], ['$', '\\'], $resolved); + + if (null !== $envBackup) { + $_ENV[$name] = $envBackup; + } + if (null !== $serverBackup) { + $_SERVER[$name] = $serverBackup; + } + if ($this->usePutenv) { + putenv("$name=$getenvBackup"); + } + + $this->values = []; + + return $resolved; + } + + private function resolveLoadedVars(): void + { + $loadedVars = array_flip(explode(',', $_SERVER['SYMFONY_DOTENV_VARS'] ?? $_ENV['SYMFONY_DOTENV_VARS'] ?? '')); + unset($loadedVars['']); + + $this->values = []; + $this->path = ''; + $this->data = ''; + $this->lineno = 0; + $this->cursor = 0; + $this->end = 0; + + // Detect variables that were originally defined as self-referencing + // (e.g. MY_VAR="${MY_VAR:-default}") so their own raw value is hidden + // during resolution, allowing the default to trigger correctly. + $selfReferencingVars = []; + foreach ($loadedVars as $name => $_) { + if ('SYMFONY_DOTENV_VARS' === $name) { + continue; + } + $value = $_ENV[$name] ?? ''; + if (str_contains($value, '$') && preg_match('/\$\{?'.preg_quote($name, '/').'(?![A-Za-z0-9_])/', $value)) { + $selfReferencingVars[$name] = true; + } + } + + for ($pass = 0; $pass < 5; ++$pass) { + $resolved = []; + foreach ($loadedVars as $name => $_) { + if ('SYMFONY_DOTENV_VARS' === $name) { + continue; + } + if (!str_contains($value = $_ENV[$name] ?? '', '$')) { + continue; + } + + if (isset($selfReferencingVars[$name])) { + $envBackup = $_ENV[$name] ?? null; + $serverBackup = $_SERVER[$name] ?? null; + unset($_ENV[$name], $_SERVER[$name]); + if ($this->usePutenv) { + $getenvBackup = $this->usePutenv ? (string) getenv($name) : null; + putenv($name); + } + } + + $resolvedValue = $this->resolveCommands($value, $loadedVars); + $resolvedValue = $this->resolveVariables($resolvedValue, $loadedVars); + + if (isset($selfReferencingVars[$name])) { + if (null !== $envBackup) { + $_ENV[$name] = $envBackup; + } + if (null !== $serverBackup) { + $_SERVER[$name] = $serverBackup; + } + if ($this->usePutenv) { + putenv("$name=$getenvBackup"); + } + } + + if ($value !== $resolvedValue) { + $resolved[$name] = $resolvedValue; + } + } + if (!$resolved) { + break; + } + $this->populate($resolved, true); + } + if (5 === $pass && $resolved) { + throw new VariableCircularReferenceException('Too many levels of variable indirection in env vars: '.implode(', ', array_keys($resolved)).'.'); + } + + // Restore literal $ signs and unescape backslashes + $restored = []; + foreach ($loadedVars as $name => $_) { + if ('SYMFONY_DOTENV_VARS' === $name) { + continue; + } + $value = $_ENV[$name] ?? ''; + if ($value !== $newValue = str_replace(["\x00", '\\\\'], ['$', '\\'], $value)) { + $restored[$name] = $newValue; + } + } + if ($restored) { + $this->populate($restored, true); + } + + $this->values = []; + unset($this->path, $this->data, $this->lineno, $this->cursor, $this->end); + } } diff --git a/lib/symfony/dotenv/Exception/VariableCircularReferenceException.php b/lib/symfony/dotenv/Exception/VariableCircularReferenceException.php new file mode 100644 index 000000000..9ad659cb0 --- /dev/null +++ b/lib/symfony/dotenv/Exception/VariableCircularReferenceException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Dotenv\Exception; + +/** + * Thrown when there are too many levels of variable indirection in env vars. + * + * @author Pascal CESCON + */ +final class VariableCircularReferenceException extends \LogicException implements ExceptionInterface +{ +} diff --git a/lib/symfony/error-handler/DebugClassLoader.php b/lib/symfony/error-handler/DebugClassLoader.php index 078f8af56..f0c120c3f 100644 --- a/lib/symfony/error-handler/DebugClassLoader.php +++ b/lib/symfony/error-handler/DebugClassLoader.php @@ -127,6 +127,21 @@ class DebugClassLoader private static array $internalMethods = []; private static array $annotatedParameters = []; private static array $darwinCache = ['/' => ['/', []]]; + /** + * @var array> + * + * Maps an interface FQCN (or an abstract class accumulating entries from its interfaces) to the list of + * "@method" annotations declared on it. For interfaces, the entry is populated directly by parsing the + * annotations from the interface's docblock. For abstract classes, the information from all implemented + * interfaces is merged together, so that the check can later be applied to the first concrete subclass. + * + * Each entry is a tuple of: + * [0] string $interface - FQCN of the interface that carries the "@method" annotation + * [1] bool $static - whether the method is declared static + * [2] string $returnType - return type from the annotation, or '' if absent + * [3] string $name - method name plus its parameter signature, e.g. "foo($arg, int $n)" + * [4] string|null $description - description text (period-normalised), or null if absent + */ private static array $method = []; private static array $returnTypes = []; private static array $methodTraits = []; @@ -398,6 +413,14 @@ class DebugClassLoader if ($refl->isInterface() && isset($doc['method'])) { foreach ($doc['method'] as $name => [$static, $returnType, $signature, $description]) { + if ($refl->hasMethod($static ? '__callStatic' : '__call')) { + // When the interface has "virtual" @method declarations but at the same time contains a __call/__callStatic magic method, + // do not trigger a deprecation notice. This is to address special use cases like in Predis' ClientInterface where the + // "@method" annotations never intend to actually add the method to the interface, but are used to document the "virtual" + // API provided by the interface through the technical implementation of magic calls. This might cause false negatives + // (missing notices) in the case that such interfaces are later amended with actual (real) methods. + continue; + } self::$method[$class][] = [$class, $static, $returnType, $name.$signature, $description]; if ('' !== $returnType) { @@ -420,6 +443,15 @@ class DebugClassLoader } } + // When the parent is a concrete class, we will trigger deprecation notices to make it aware that it needs + // to add the new methods announced with @method. The parent will have to provide all those methods. + // For child classes this means they will not need to deal with @method coming from any of the interfaces + // the parent implements. + // Put those interfaces that we can ignore into $parentInterfaces. + // The ternary makes use of the fact that abstract parent classes will accumulate the methods in self::$method, + // so !isset(self::$method[$parent]) indicates a concrete parent class. + $parentInterfaces = ($parent && !isset(self::$method[$parent])) ? class_implements($parent, false) : []; + // Detect if the parent is annotated foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) { if (!isset(self::$checkedClasses[$use])) { @@ -435,13 +467,15 @@ class DebugClassLoader $deprecations[] = \sprintf('The "%s" %s is considered internal%s It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $className); } if (isset(self::$method[$use])) { - if ($refl->isAbstract()) { + if ($refl->isAbstract() || $refl->isInterface()) { + // Abstract classes and interfaces inherit @method from interfaces they + // implement directly or through inheritance. if (isset(self::$method[$class])) { self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]); } else { self::$method[$class] = self::$method[$use]; } - } elseif (!$refl->isInterface()) { + } else { if (!strncmp($vendor, str_replace('_', '\\', $use), $vendorLen) && str_starts_with($className, 'Symfony\\') && (!class_exists(InstalledVersions::class) @@ -450,14 +484,14 @@ class DebugClassLoader // skip "same vendor" @method deprecations for Symfony\* classes unless symfony/symfony is being tested continue; } - $hasCall = $refl->hasMethod('__call'); - $hasStaticCall = $refl->hasMethod('__callStatic'); foreach (self::$method[$use] as [$interface, $static, $returnType, $name, $description]) { - if ($static ? $hasStaticCall : $hasCall) { + if (isset($parentInterfaces[$interface])) { + // The @method annotation comes from an interface that has already been implemented by a concrete parent class, + // so we can ignore it here. continue; } $realName = substr($name, 0, strpos($name, '(')); - if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) { + if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static xor $methodRefl->isStatic())) { $deprecations[] = \sprintf('Class "%s" should implement method "%s::%s%s"%s', $className, ($static ? 'static ' : '').$interface, $name, $returnType ? ': '.$returnType : '', null === $description ? '.' : ': '.$description); } } 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/event-dispatcher/Debug/TraceableEventDispatcher.php b/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php index 2faea0463..12ebb1e67 100644 --- a/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php +++ b/lib/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php @@ -40,6 +40,9 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa private EventDispatcherInterface $dispatcher; private array $wrappedListeners = []; private array $orphanedEvents = []; + private array $dispatchDepth = []; + private array $calledListenerInfos = []; + private array $calledOriginalListeners = []; private ?RequestStack $requestStack; private string $currentRequestHash = ''; @@ -155,20 +158,20 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa public function getCalledListeners(?Request $request = null): array { - if (null === $this->callStack) { + if (!$this->calledListenerInfos) { return []; } $hash = $request ? spl_object_hash($request) : null; $called = []; - foreach ($this->callStack as $listener) { - [$eventName, $requestHash] = $this->callStack->getInfo(); + + foreach ($this->calledListenerInfos as $requestHash => $infos) { if (null === $hash || $hash === $requestHash) { - $called[] = $listener->getInfo($eventName); + $called[] = $infos; } } - return $called; + return $called ? array_merge(...$called) : []; } public function getNotCalledListeners(?Request $request = null): array @@ -185,16 +188,14 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa $hash = $request ? spl_object_hash($request) : null; $calledListeners = []; - if (null !== $this->callStack) { - foreach ($this->callStack as $calledListener) { - [, $requestHash] = $this->callStack->getInfo(); - - if (null === $hash || $hash === $requestHash) { - $calledListeners[] = $calledListener->getWrappedListener(); - } + foreach ($this->calledOriginalListeners as $requestHash => $eventListeners) { + if (null === $hash || $hash === $requestHash) { + $calledListeners[] = array_merge(...array_values($eventListeners)); } } + $calledListeners = $calledListeners ? array_merge(...$calledListeners) : []; + $notCalled = []; foreach ($allListeners as $eventName => $listeners) { @@ -234,6 +235,9 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa $this->callStack = null; $this->orphanedEvents = []; $this->currentRequestHash = ''; + $this->dispatchDepth = []; + $this->calledListenerInfos = []; + $this->calledOriginalListeners = []; } /** @@ -267,6 +271,8 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa private function preProcess(string $eventName): void { + $this->dispatchDepth[$eventName] = ($this->dispatchDepth[$eventName] ?? 0) + 1; + if (!$this->dispatcher->hasListeners($eventName)) { $this->orphanedEvents[$this->currentRequestHash][] = $eventName; @@ -285,6 +291,8 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa private function postProcess(string $eventName): void { + --$this->dispatchDepth[$eventName]; + unset($this->wrappedListeners[$eventName]); $skipped = false; foreach ($this->dispatcher->getListeners($eventName) as $listener) { @@ -302,10 +310,16 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa if ($listener->wasCalled()) { $this->logger?->debug('Notified event "{event}" to listener "{listener}".', $context); - } else { - unset($this->callStack[$listener]); + + $original = $listener->getWrappedListener(); + if (!\in_array($original, $this->calledOriginalListeners[$this->currentRequestHash][$eventName] ?? [], true)) { + $this->calledOriginalListeners[$this->currentRequestHash][$eventName][] = $original; + $this->calledListenerInfos[$this->currentRequestHash][] = $listener->getInfo($eventName); + } } + unset($this->callStack[$listener]); + if (null !== $this->logger && $skipped) { $this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context); } @@ -316,6 +330,28 @@ class TraceableEventDispatcher implements EventDispatcherInterface, ResetInterfa $skipped = true; } } + + if (0 < $this->dispatchDepth[$eventName]) { + return; + } + + // Clean up stale callStack entries left by nested same-event dispatches + $stale = []; + foreach ($this->callStack as $listener) { + if ($this->callStack->getInfo()[0] === $eventName) { + $stale[] = $listener; + } + } + foreach ($stale as $listener) { + if ($listener->wasCalled()) { + $original = $listener->getWrappedListener(); + if (!\in_array($original, $this->calledOriginalListeners[$this->currentRequestHash][$eventName] ?? [], true)) { + $this->calledOriginalListeners[$this->currentRequestHash][$eventName][] = $original; + $this->calledListenerInfos[$this->currentRequestHash][] = $listener->getInfo($eventName); + } + } + unset($this->callStack[$listener]); + } } private function sortNotCalledListeners(array $a, array $b): int diff --git a/lib/symfony/form/Extension/Validator/ValidatorExtension.php b/lib/symfony/form/Extension/Validator/ValidatorExtension.php index bfad8074f..95effe760 100644 --- a/lib/symfony/form/Extension/Validator/ValidatorExtension.php +++ b/lib/symfony/form/Extension/Validator/ValidatorExtension.php @@ -39,17 +39,23 @@ class ValidatorExtension extends AbstractExtension /** @var ClassMetadata $metadata */ $metadata = $validator->getMetadataFor(\Symfony\Component\Form\Form::class); + $this->validator = $validator; + $this->formRenderer = $formRenderer; + $this->translator = $translator; + // Register the form constraints in the validator programmatically. // This functionality is required when using the Form component without // the DIC, where the XML file is loaded automatically. Thus the following // code must be kept synchronized with validation.xml + foreach ($metadata->getConstraints() as $constraint) { + if ($constraint instanceof Form) { + return; + } + } + $metadata->addConstraint(new Form()); $metadata->addConstraint(new Traverse(false)); - - $this->validator = $validator; - $this->formRenderer = $formRenderer; - $this->translator = $translator; } public function loadTypeGuesser(): ?FormTypeGuesserInterface diff --git a/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php b/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php index 20810098a..ec962ff98 100644 --- a/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php +++ b/lib/symfony/framework-bundle/DependencyInjection/FrameworkExtension.php @@ -1233,8 +1233,7 @@ class FrameworkExtension extends Extension $container->setParameter('request_listener.https_port', $config['https_port']); if (null !== $config['default_uri']) { - $container->getDefinition('router.request_context') - ->replaceArgument(0, $config['default_uri']); + $container->setParameter('router.request_context.base_url', $config['default_uri']); } if ($this->isInitializedConfigEnabled('annotations') && (new \ReflectionClass(AttributeClassLoader::class))->hasProperty('reader')) { @@ -1265,6 +1264,7 @@ class FrameworkExtension extends Extension } $container->setParameter('session.storage.options', $options); + $container->setParameter('session.metadata.cookie_lifetime', $options['cookie_lifetime'] ?? null); // session handler (the internal callback registered with PHP session management) if (null === $config['handler_id']) { diff --git a/lib/symfony/framework-bundle/Resources/config/session.php b/lib/symfony/framework-bundle/Resources/config/session.php index 2e481359a..649c5cd71 100644 --- a/lib/symfony/framework-bundle/Resources/config/session.php +++ b/lib/symfony/framework-bundle/Resources/config/session.php @@ -43,6 +43,7 @@ return static function (ContainerConfigurator $container) { ->args([ param('session.metadata.storage_key'), param('session.metadata.update_threshold'), + param('session.metadata.cookie_lifetime'), ]), false, ]) @@ -53,6 +54,7 @@ return static function (ContainerConfigurator $container) { ->args([ param('session.metadata.storage_key'), param('session.metadata.update_threshold'), + param('session.metadata.cookie_lifetime'), ]), false, ]) @@ -64,6 +66,7 @@ return static function (ContainerConfigurator $container) { ->args([ param('session.metadata.storage_key'), param('session.metadata.update_threshold'), + param('session.metadata.cookie_lifetime'), ]), ]) diff --git a/lib/symfony/framework-bundle/Test/KernelTestCase.php b/lib/symfony/framework-bundle/Test/KernelTestCase.php index 5a6384b5e..2b49083fa 100644 --- a/lib/symfony/framework-bundle/Test/KernelTestCase.php +++ b/lib/symfony/framework-bundle/Test/KernelTestCase.php @@ -12,10 +12,12 @@ namespace Symfony\Bundle\FrameworkBundle\Test; use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Resource\SelfCheckingResourceChecker; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Contracts\Service\ResetInterface; @@ -38,6 +40,8 @@ abstract class KernelTestCase extends TestCase protected static $booted = false; + private static bool $kernelHasBeenRebooted = false; + protected function tearDown(): void { static::ensureKernelShutdown(); @@ -88,6 +92,7 @@ abstract class KernelTestCase extends TestCase // reboot a fresh one. if ($kernel->getContainer()->initialized('cache_warmer')) { static::ensureKernelShutdown(); + self::$kernelHasBeenRebooted = true; $kernel = static::createKernel($options); $kernel->boot(); @@ -161,6 +166,20 @@ abstract class KernelTestCase extends TestCase static::$kernel->shutdown(); static::$booted = false; + if (self::$kernelHasBeenRebooted) { + self::$kernelHasBeenRebooted = false; + try { + (new \ReflectionProperty(Kernel::class, 'freshCache'))->setValue(null, []); + } catch (\ReflectionException) { + // ignore if the property doesn't exist + } + try { + (new \ReflectionProperty(SelfCheckingResourceChecker::class, 'cache'))->setValue(null, []); + } catch (\ReflectionException) { + // ignore if the property doesn't exist + } + } + if ($container instanceof ResetInterface) { $container->reset(); } diff --git a/lib/symfony/http-foundation/Session/Storage/MetadataBag.php b/lib/symfony/http-foundation/Session/Storage/MetadataBag.php index 5bb4cfbc7..5192d14c1 100644 --- a/lib/symfony/http-foundation/Session/Storage/MetadataBag.php +++ b/lib/symfony/http-foundation/Session/Storage/MetadataBag.php @@ -41,14 +41,18 @@ class MetadataBag implements SessionBagInterface private int $updateThreshold; + private ?int $cookieLifetime; + /** - * @param string $storageKey The key used to store bag in the session - * @param int $updateThreshold The time to wait between two UPDATED updates + * @param string $storageKey The key used to store bag in the session + * @param int $updateThreshold The time to wait between two UPDATED updates + * @param int|null $cookieLifetime The configured cookie lifetime; null to read from php.ini */ - public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0) + public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0, ?int $cookieLifetime = null) { $this->storageKey = $storageKey; $this->updateThreshold = $updateThreshold; + $this->cookieLifetime = $cookieLifetime; } /** @@ -143,6 +147,6 @@ class MetadataBag implements SessionBagInterface { $timeStamp = time(); $this->meta[self::CREATED] = $this->meta[self::UPDATED] = $this->lastUsed = $timeStamp; - $this->meta[self::LIFETIME] = $lifetime ?? (int) \ini_get('session.cookie_lifetime'); + $this->meta[self::LIFETIME] = $lifetime ?? $this->cookieLifetime ?? (int) \ini_get('session.cookie_lifetime'); } } diff --git a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php b/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php index e3a092e7b..493136920 100644 --- a/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php +++ b/lib/symfony/http-kernel/Controller/ArgumentResolver/RequestPayloadValueResolver.php @@ -105,7 +105,7 @@ class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscr try { $payload = $this->$payloadMapper($request, $type, $argument); } catch (PartialDenormalizationException $e) { - $trans = $this->translator ? $this->translator->trans(...) : fn ($m, $p) => strtr($m, $p); + $trans = $this->translator ? $this->translator->trans(...) : static fn ($m, $p) => strtr($m, $p); foreach ($e->getErrors() as $error) { $parameters = []; $template = 'This value was of an unexpected type.'; @@ -187,7 +187,7 @@ class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscr } if (\is_array($data)) { - return $this->serializer->denormalize($data, $type, 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE); + return $this->serializer->denormalize($data, $type, self::hasNonStringScalar($data) ? $format : 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE); } if ('form' === $format) { @@ -202,4 +202,21 @@ class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscr throw new HttpException(Response::HTTP_BAD_REQUEST, \sprintf('Request payload contains invalid "%s" data.', $format), $e); } } + + private static function hasNonStringScalar(array $data): bool + { + $stack = [$data]; + + while ($stack) { + foreach (array_pop($stack) as $v) { + if (\is_array($v)) { + $stack[] = $v; + } elseif (!\is_string($v)) { + return true; + } + } + } + + return false; + } } diff --git a/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index 5be3f650e..cc58079eb 100644 --- a/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/lib/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -171,6 +171,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface } if ($autowireAttributes) { + $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; $attribute = $autowireAttributes[0]->newInstance(); $value = $parameterBag->resolveValue($attribute->value); diff --git a/lib/symfony/http-kernel/EventListener/LocaleListener.php b/lib/symfony/http-kernel/EventListener/LocaleListener.php index a3aa30f09..875551b5f 100644 --- a/lib/symfony/http-kernel/EventListener/LocaleListener.php +++ b/lib/symfony/http-kernel/EventListener/LocaleListener.php @@ -47,6 +47,7 @@ class LocaleListener implements EventSubscriberInterface public function setDefaultLocale(KernelEvent $event): void { $event->getRequest()->setDefaultLocale($this->defaultLocale); + $this->setRouterLocale($this->defaultLocale); } public function onKernelRequest(RequestEvent $event): void @@ -54,14 +55,12 @@ class LocaleListener implements EventSubscriberInterface $request = $event->getRequest(); $this->setLocale($request); - $this->setRouterContext($request); + $this->setRouterLocale($request->getLocale()); } public function onKernelFinishRequest(FinishRequestEvent $event): void { - if (null !== $parentRequest = $this->requestStack->getParentRequest()) { - $this->setRouterContext($parentRequest); - } + $this->setRouterLocale($this->requestStack->getParentRequest()?->getLocale() ?? $this->defaultLocale); } private function setLocale(Request $request): void @@ -76,9 +75,9 @@ class LocaleListener implements EventSubscriberInterface } } - private function setRouterContext(Request $request): void + private function setRouterLocale(string $locale): void { - $this->router?->getContext()->setParameter('_locale', $request->getLocale()); + $this->router?->getContext()->setParameter('_locale', $locale); } public static function getSubscribedEvents(): array diff --git a/lib/symfony/http-kernel/Kernel.php b/lib/symfony/http-kernel/Kernel.php index cb148d4d2..2c279f1a8 100644 --- a/lib/symfony/http-kernel/Kernel.php +++ b/lib/symfony/http-kernel/Kernel.php @@ -77,11 +77,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ private static array $freshCache = []; - public const VERSION = '6.4.34'; - public const VERSION_ID = 60434; + public const VERSION = '6.4.36'; + public const VERSION_ID = 60436; public const MAJOR_VERSION = 6; public const MINOR_VERSION = 4; - public const RELEASE_VERSION = 34; + public const RELEASE_VERSION = 36; public const EXTRA_VERSION = ''; public const END_OF_MAINTENANCE = '11/2026'; diff --git a/lib/symfony/mime/FileBinaryMimeTypeGuesser.php b/lib/symfony/mime/FileBinaryMimeTypeGuesser.php index 465f061a0..f290f9a3a 100644 --- a/lib/symfony/mime/FileBinaryMimeTypeGuesser.php +++ b/lib/symfony/mime/FileBinaryMimeTypeGuesser.php @@ -44,15 +44,11 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface return $supported; } - if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('passthru') || !\function_exists('escapeshellarg')) { + if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('shell_exec') || !\function_exists('escapeshellarg')) { return $supported = false; } - ob_start(); - passthru('command -v file', $exitStatus); - $binPath = trim(ob_get_clean()); - - return $supported = 0 === $exitStatus && '' !== $binPath; + return $supported = '' !== trim(shell_exec('command -v file') ?: ''); } public function guessMimeType(string $path): ?string @@ -65,17 +61,8 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface throw new LogicException(\sprintf('The "%s" guesser is not supported.', __CLASS__)); } - ob_start(); - // need to use --mime instead of -i. see #6641 - passthru(\sprintf($this->cmd, escapeshellarg((str_starts_with($path, '-') ? './' : '').$path)), $return); - if ($return > 0) { - ob_end_clean(); - - return null; - } - - $type = trim(ob_get_clean()); + $type = trim(shell_exec(\sprintf($this->cmd, escapeshellarg((str_starts_with($path, '-') ? './' : '').$path))) ?: ''); if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\+\.]+)#i', $type, $match)) { // it's not a type, but an error message diff --git a/lib/symfony/mime/Part/DataPart.php b/lib/symfony/mime/Part/DataPart.php index f550f31fc..e3d0fcfae 100644 --- a/lib/symfony/mime/Part/DataPart.php +++ b/lib/symfony/mime/Part/DataPart.php @@ -141,7 +141,7 @@ class DataPart extends TextPart } $this->_headers = $this->getHeaders(); - return ['_headers', '_parent', 'filename', 'mediaType']; + return ['_headers', '_parent', 'filename', 'mediaType', 'cid']; } /** diff --git a/lib/symfony/polyfill-ctype/Ctype.php b/lib/symfony/polyfill-ctype/Ctype.php index ba75a2c95..e26cc0221 100644 --- a/lib/symfony/polyfill-ctype/Ctype.php +++ b/lib/symfony/polyfill-ctype/Ctype.php @@ -211,6 +211,10 @@ final class Ctype */ private static function convert_int_to_char_for_ctype($int, $function) { + if (\PHP_VERSION_ID >= 80100 && !\is_string($int)) { + @trigger_error($function.'(): Argument of type '.get_debug_type($int).' will be interpreted as string in the future', \E_USER_DEPRECATED); + } + if (!\is_int($int)) { return $int; } @@ -219,10 +223,6 @@ final class Ctype return (string) $int; } - if (\PHP_VERSION_ID >= 80100) { - @trigger_error($function.'(): Argument of type int will be interpreted as string in the future', \E_USER_DEPRECATED); - } - if ($int < 0) { $int += 256; } diff --git a/lib/symfony/polyfill-intl-grapheme/Grapheme.php b/lib/symfony/polyfill-intl-grapheme/Grapheme.php index f9e9e5741..51efbf163 100644 --- a/lib/symfony/polyfill-intl-grapheme/Grapheme.php +++ b/lib/symfony/polyfill-intl-grapheme/Grapheme.php @@ -27,6 +27,7 @@ namespace Symfony\Polyfill\Intl\Grapheme; * - grapheme_strstr - Returns part of haystack string from the first occurrence of needle to the end of haystack * - grapheme_substr - Return part of a string * - grapheme_str_split - Splits a string into an array of individual or chunks of graphemes + * - grapheme_levenshtein - Calculate the grapheme-unit Levenshtein distance between two strings * * @author Nicolas Grekas * @@ -51,7 +52,7 @@ final class Grapheme if (!\is_scalar($s)) { $hasError = false; - set_error_handler(function () use (&$hasError) { $hasError = true; }); + set_error_handler(static function () use (&$hasError) { $hasError = true; }); $next = substr($s, $start); restore_error_handler(); if ($hasError) { @@ -223,6 +224,54 @@ final class Grapheme return $chunks; } + public static function grapheme_levenshtein($s1, $s2, $insertion_cost = 1, $replacement_cost = 1, $deletion_cost = 1) + { + if (!preg_match('//u', $s1) || !preg_match('//u', $s2)) { + return false; + } + + if (0 > $insertion_cost || 0 > $replacement_cost || 0 > $deletion_cost) { + if (80000 > \PHP_VERSION_ID) { + return false; + } + + throw new \ValueError('grapheme_levenshtein(): Argument #3 ($insertion_cost), #4 ($replacement_cost), and #5 ($deletion_cost) must be greater than or equal to 0'); + } + + preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s1, $s1); + preg_match_all('/'.SYMFONY_GRAPHEME_CLUSTER_RX.'/u', $s2, $s2); + + $s1 = $s1[0]; + $s2 = $s2[0]; + $l1 = \count($s1); + $l2 = \count($s2); + + if (0 === $l1) { + return $l2 * $insertion_cost; + } + if (0 === $l2) { + return $l1 * $deletion_cost; + } + + $dp = array_fill(0, $l1 + 1, array_fill(0, $l2 + 1, 0)); + + for ($i = 1; $i <= $l1; ++$i) { + $dp[$i][0] = $dp[$i - 1][0] + $deletion_cost; + } + for ($j = 1; $j <= $l2; ++$j) { + $dp[0][$j] = $dp[0][$j - 1] + $insertion_cost; + } + + for ($i = 1; $i <= $l1; ++$i) { + for ($j = 1; $j <= $l2; ++$j) { + $cost = ($s1[$i - 1] === $s2[$j - 1]) ? 0 : $replacement_cost; + $dp[$i][$j] = min($dp[$i - 1][$j] + $deletion_cost, $dp[$i][$j - 1] + $insertion_cost, $dp[$i - 1][$j - 1] + $cost); + } + } + + return $dp[$l1][$l2]; + } + private static function grapheme_position($s, $needle, $offset, $mode) { $needle = (string) $needle; diff --git a/lib/symfony/polyfill-intl-grapheme/bootstrap.php b/lib/symfony/polyfill-intl-grapheme/bootstrap.php index 374dbd3a7..8926c3b0f 100644 --- a/lib/symfony/polyfill-intl-grapheme/bootstrap.php +++ b/lib/symfony/polyfill-intl-grapheme/bootstrap.php @@ -53,5 +53,8 @@ if (!function_exists('grapheme_substr')) { function grapheme_substr($string, $offset, $length = null) { return p\Grapheme::grapheme_substr($string, $offset, $length); } } if (!function_exists('grapheme_str_split')) { - function grapheme_str_split($string, $length = 1) { return p\Grapheme::grapheme_str_split($string, $length); } + function grapheme_str_split(string $string, int $length = 1) { return p\Grapheme::grapheme_str_split($string, $length); } +} +if (!function_exists('grapheme_levenshtein')) { + function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = '') { return p\Php85::grapheme_levenshtein($string1, $string2, $insertion_cost, $replacement_cost, $deletion_cost); } } diff --git a/lib/symfony/polyfill-intl-grapheme/bootstrap80.php b/lib/symfony/polyfill-intl-grapheme/bootstrap80.php index d71175530..acf046215 100644 --- a/lib/symfony/polyfill-intl-grapheme/bootstrap80.php +++ b/lib/symfony/polyfill-intl-grapheme/bootstrap80.php @@ -14,6 +14,9 @@ use Symfony\Polyfill\Intl\Grapheme as p; if (!function_exists('grapheme_str_split')) { function grapheme_str_split(string $string, int $length = 1): array|false { return p\Grapheme::grapheme_str_split($string, $length); } } +if (!function_exists('grapheme_levenshtein')) { + function grapheme_levenshtein(string $string1, string $string2, int $insertion_cost = 1, int $replacement_cost = 1, int $deletion_cost = 1, string $locale = ''): int|false { return p\Grapheme::grapheme_levenshtein($string1, $string2, $insertion_cost, $replacement_cost, $deletion_cost); } +} if (extension_loaded('intl')) { return; diff --git a/lib/symfony/polyfill-intl-icu/Collator.php b/lib/symfony/polyfill-intl-icu/Collator.php index 2f952cdf5..5055bc4b0 100644 --- a/lib/symfony/polyfill-intl-icu/Collator.php +++ b/lib/symfony/polyfill-intl-icu/Collator.php @@ -118,17 +118,15 @@ abstract class Collator } /** - * Not supported. Compare two Unicode strings. + * Compare two Unicode strings. * * @return int|false * * @see https://php.net/collator.compare - * - * @throws MethodNotImplementedException */ public function compare(string $string1, string $string2) { - throw new MethodNotImplementedException(__METHOD__); + return strcasecmp($string1, $string2) ?: $string2 <=> $string1; } /** diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php index 02d071da5..ee871182a 100644 --- a/lib/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php +++ b/lib/symfony/polyfill-intl-icu/DateFormat/FullTransformer.php @@ -104,7 +104,7 @@ class FullTransformer // handle unimplemented characters if (false !== strpos($this->notImplementedChars, $dateChars[0])) { - throw new NotImplementedException(sprintf('Unimplemented date character "%s" in format "%s".', $dateChars[0], $this->pattern)); + throw new NotImplementedException(\sprintf('Unimplemented date character "%s" in format "%s".', $dateChars[0], $this->pattern)); } return ''; @@ -212,7 +212,7 @@ class FullTransformer { $specialCharsArray = str_split($specialChars); - $specialCharsMatch = implode('|', array_map(function ($char) { + $specialCharsMatch = implode('|', array_map(static function ($char) { return $char.'+'; }, $specialCharsArray)); diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php index 6712ed282..c54025b77 100644 --- a/lib/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php +++ b/lib/symfony/polyfill-intl-icu/DateFormat/MonthTransformer.php @@ -53,7 +53,7 @@ class MonthTransformer extends Transformer public function __construct() { if (0 === \count(self::$shortMonths)) { - self::$shortMonths = array_map(function ($month) { + self::$shortMonths = array_map(static function ($month) { return substr($month, 0, 3); }, self::$months); diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php index a549deeda..303e66d61 100644 --- a/lib/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php +++ b/lib/symfony/polyfill-intl-icu/DateFormat/QuarterTransformer.php @@ -39,9 +39,9 @@ class QuarterTransformer extends Transformer $map = [1 => '1st quarter', 2 => '2nd quarter', 3 => '3rd quarter', 4 => '4th quarter']; return $map[$quarter]; - } else { - return $quarter; } + + return $quarter; } } diff --git a/lib/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php b/lib/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php index bab7a96f8..d9fb64d03 100644 --- a/lib/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php +++ b/lib/symfony/polyfill-intl-icu/DateFormat/TimezoneTransformer.php @@ -55,7 +55,7 @@ class TimezoneTransformer extends Transformer return $dateTime->format('\G\M\TP'); } - return sprintf('GMT%s%d', $offset >= 0 ? '+' : '', $offset / 100); + return \sprintf('GMT%s%d', $offset >= 0 ? '+' : '', $offset / 100); } public function getReverseMatchingRegExp(int $length): string @@ -97,12 +97,12 @@ class TimezoneTransformer extends Transformer $signal = '-' === $matches['signal'] ? '+' : '-'; if (0 < $minutes) { - throw new NotImplementedException(sprintf('It is not possible to use a GMT time zone with minutes offset different than zero (0). GMT time zone tried: "%s".', $formattedTimeZone)); + throw new NotImplementedException(\sprintf('It is not possible to use a GMT time zone with minutes offset different than zero (0). GMT time zone tried: "%s".', $formattedTimeZone)); } return 'Etc/GMT'.(0 !== $hours ? $signal.$hours : ''); } - throw new \InvalidArgumentException(sprintf('The GMT time zone "%s" does not match with the supported formats GMT[+-]HH:MM or GMT[+-]HHMM.', $formattedTimeZone)); + throw new \InvalidArgumentException(\sprintf('The GMT time zone "%s" does not match with the supported formats GMT[+-]HH:MM or GMT[+-]HHMM.', $formattedTimeZone)); } } diff --git a/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php b/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php index db120a340..22cd5847a 100644 --- a/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php +++ b/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentNotImplementedException.php @@ -22,7 +22,7 @@ class MethodArgumentNotImplementedException extends NotImplementedException */ public function __construct(string $methodName, string $argName) { - $message = sprintf('The %s() method\'s argument $%s behavior is not implemented.', $methodName, $argName); + $message = \sprintf('The %s() method\'s argument $%s behavior is not implemented.', $methodName, $argName); parent::__construct($message); } } diff --git a/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php b/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php index bd9204234..d1f0876b8 100644 --- a/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php +++ b/lib/symfony/polyfill-intl-icu/Exception/MethodArgumentValueNotImplementedException.php @@ -24,7 +24,7 @@ class MethodArgumentValueNotImplementedException extends NotImplementedException */ public function __construct(string $methodName, string $argName, $argValue, string $additionalMessage = '') { - $message = sprintf( + $message = \sprintf( 'The %s() method\'s argument $%s value %s behavior is not implemented.%s', $methodName, $argName, diff --git a/lib/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php b/lib/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php index 9e1a43985..494bf7a0f 100644 --- a/lib/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php +++ b/lib/symfony/polyfill-intl-icu/Exception/MethodNotImplementedException.php @@ -21,6 +21,6 @@ class MethodNotImplementedException extends NotImplementedException */ public function __construct(string $methodName) { - parent::__construct(sprintf('The %s() is not implemented.', $methodName)); + parent::__construct(\sprintf('The %s() is not implemented.', $methodName)); } } diff --git a/lib/symfony/polyfill-intl-icu/Icu.php b/lib/symfony/polyfill-intl-icu/Icu.php index b9590f43d..702d1b83d 100644 --- a/lib/symfony/polyfill-intl-icu/Icu.php +++ b/lib/symfony/polyfill-intl-icu/Icu.php @@ -108,10 +108,10 @@ abstract class Icu public static function setError(int $code, string $message = '') { if (!isset(self::$errorCodes[$code])) { - throw new \InvalidArgumentException(sprintf('No such error code: "%s".', $code)); + throw new \InvalidArgumentException(\sprintf('No such error code: "%s".', $code)); } - self::$errorMessage = $message ? sprintf('%s: %s', $message, self::$errorCodes[$code]) : self::$errorCodes[$code]; + self::$errorMessage = $message ? \sprintf('%s: %s', $message, self::$errorCodes[$code]) : self::$errorCodes[$code]; self::$errorCode = $code; } } diff --git a/lib/symfony/polyfill-intl-icu/IntlDateFormatter.php b/lib/symfony/polyfill-intl-icu/IntlDateFormatter.php index b2674f906..750f69b00 100644 --- a/lib/symfony/polyfill-intl-icu/IntlDateFormatter.php +++ b/lib/symfony/polyfill-intl-icu/IntlDateFormatter.php @@ -225,7 +225,7 @@ abstract class IntlDateFormatter // behave like the intl extension $argumentError = null; if (!\is_int($datetime) && !$datetime instanceof \DateTimeInterface) { - $argumentError = sprintf('datefmt_format: string \'%s\' is not numeric, which would be required for it to be a valid date', $datetime); + $argumentError = \sprintf('datefmt_format: string \'%s\' is not numeric, which would be required for it to be a valid date', $datetime); } if (null !== $argumentError) { diff --git a/lib/symfony/polyfill-intl-icu/IntlListFormatter.php b/lib/symfony/polyfill-intl-icu/IntlListFormatter.php new file mode 100644 index 000000000..9dc7ca91f --- /dev/null +++ b/lib/symfony/polyfill-intl-icu/IntlListFormatter.php @@ -0,0 +1,169 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Intl\Icu; + +/** + * @author Ayesh Karunaratne + * + * @internal + */ +class IntlListFormatter +{ + public const TYPE_AND = 0; + public const TYPE_OR = 1; + public const TYPE_UNITS = 2; + + public const WIDTH_WIDE = 0; + public const WIDTH_SHORT = 1; + public const WIDTH_NARROW = 2; + + private $type; + private $width; + + private const TYPE_MAP = [ + self::TYPE_AND => 'standard', + self::TYPE_OR => 'or', + self::TYPE_UNITS => 'unit', + ]; + + private const WIDTH_MAP = [ + self::WIDTH_WIDE => '', + self::WIDTH_SHORT => '-short', + self::WIDTH_NARROW => '-narrow', + ]; + + private const EN_LIST_PATTERNS = [ + 'listPattern-type-standard' => [ + 'start' => '{0}, {1}', + 'middle' => '{0}, {1}', + 'end' => '{0}, and {1}', + 2 => '{0} and {1}', + ], + 'listPattern-type-or' => [ + 'start' => '{0}, {1}', + 'middle' => '{0}, {1}', + 'end' => '{0}, or {1}', + 2 => '{0} or {1}', + ], + 'listPattern-type-or-narrow' => [ + 'start' => '{0}, {1}', + 'middle' => '{0}, {1}', + 'end' => '{0}, or {1}', + 2 => '{0} or {1}', + ], + 'listPattern-type-or-short' => [ + 'start' => '{0}, {1}', + 'middle' => '{0}, {1}', + 'end' => '{0}, or {1}', + 2 => '{0} or {1}', + ], + 'listPattern-type-standard-narrow' => [ + 'start' => '{0}, {1}', + 'middle' => '{0}, {1}', + 'end' => '{0}, {1}', + 2 => '{0}, {1}', + ], + 'listPattern-type-standard-short' => [ + 'start' => '{0}, {1}', + 'middle' => '{0}, {1}', + 'end' => '{0}, & {1}', + 2 => '{0} & {1}', + ], + 'listPattern-type-unit' => [ + 'start' => '{0}, {1}', + 'middle' => '{0}, {1}', + 'end' => '{0}, {1}', + 2 => '{0}, {1}', + ], + 'listPattern-type-unit-narrow' => [ + 'start' => '{0} {1}', + 'middle' => '{0} {1}', + 'end' => '{0} {1}', + 2 => '{0} {1}', + ], + 'listPattern-type-unit-short' => [ + 'start' => '{0}, {1}', + 'middle' => '{0}, {1}', + 'end' => '{0}, {1}', + 2 => '{0}, {1}', + ], + ]; + + public function __construct(string $locale, int $type = self::TYPE_AND, int $width = self::WIDTH_WIDE) + { + if ('en' !== $locale && 0 !== strpos($locale, 'en')) { + if (80000 > \PHP_VERSION_ID) { + throw new \InvalidArgumentException('Invalid locale, only "en" and "en-*" locales are supported.'); + } + + throw new \ValueError('Invalid locale, only "en" and "en-*" locales are supported.'); + } + + if (!isset(self::TYPE_MAP[$type])) { + if (80000 > \PHP_VERSION_ID) { + throw new \InvalidArgumentException('Argument #2 ($type) must be one of IntlListFormatter::TYPE_AND, IntlListFormatter::TYPE_OR, or IntlListFormatter::TYPE_UNITS.'); + } + + throw new \ValueError('Argument #2 ($type) must be one of IntlListFormatter::TYPE_AND, IntlListFormatter::TYPE_OR, or IntlListFormatter::TYPE_UNITS.'); + } + + if (!isset(self::WIDTH_MAP[$width])) { + if (80000 > \PHP_VERSION_ID) { + throw new \InvalidArgumentException('Argument #3 ($width) must be one of IntlListFormatter::WIDTH_WIDE, IntlListFormatter::WIDTH_SHORT, or IntlListFormatter::WIDTH_NARROW.'); + } + + throw new \ValueError('Argument #3 ($width) must be one of IntlListFormatter::WIDTH_WIDE, IntlListFormatter::WIDTH_SHORT, or IntlListFormatter::WIDTH_NARROW.'); + } + + $this->type = $type; + $this->width = $width; + } + + public function format(array $strings): string + { + $count = \count($strings); + + if (0 === $count) { + return ''; + } + + $strings = array_values($strings); + + if (1 === $count) { + return (string) $strings[0]; + } + + $pattern = self::EN_LIST_PATTERNS['listPattern-type-'.self::TYPE_MAP[$this->type].self::WIDTH_MAP[$this->width]]; + + if (2 === $count) { + return strtr($pattern[2], ['{0}' => (string) $strings[0], '{1}' => (string) $strings[1]]); + } + + $result = strtr($pattern['start'], ['{0}' => (string) $strings[0], '{1}' => (string) $strings[1]]); + + for ($i = 2; $i < $count - 1; ++$i) { + $result = strtr($pattern['middle'], ['{0}' => $result, '{1}' => (string) $strings[$i]]); + } + + return strtr($pattern['end'], ['{0}' => $result, '{1}' => (string) $strings[$count - 1]]); + } + + public function getErrorCode(): int + { + return 0; + } + + public function getErrorMessage(): string + { + return ''; + } +} diff --git a/lib/symfony/polyfill-intl-icu/Locale.php b/lib/symfony/polyfill-intl-icu/Locale.php index f449fd5df..516c10b64 100644 --- a/lib/symfony/polyfill-intl-icu/Locale.php +++ b/lib/symfony/polyfill-intl-icu/Locale.php @@ -41,6 +41,28 @@ abstract class Locale public const GRANDFATHERED_LANG_TAG = 'grandfathered'; public const PRIVATE_TAG = 'private'; + private const RTL_SCRIPTS = [ + 'Adlm' => true, 'Arab' => true, 'Armi' => true, 'Hebr' => true, + 'Mand' => true, 'Mani' => true, 'Mend' => true, 'Nkoo' => true, + 'Orkh' => true, 'Phnx' => true, 'Rohg' => true, 'Samr' => true, + 'Syrc' => true, 'Thaa' => true, 'Yezi' => true, + ]; + + private const LANG_TO_SCRIPT = [ + 'ar' => 'Arab', + 'ckb' => 'Arab', + 'dv' => 'Thaa', + 'fa' => 'Arab', + 'he' => 'Hebr', + 'ku' => 'Arab', + 'nqo' => 'Nkoo', + 'ps' => 'Arab', + 'sd' => 'Arab', + 'ug' => 'Arab', + 'ur' => 'Arab', + 'yi' => 'Hebr', + ]; + /** * Not supported. Returns the best available locale based on HTTP "Accept-Language" header according to RFC 2616. * @@ -307,4 +329,22 @@ abstract class Locale return true; } + + public static function isRightToLeft(string $locale): bool + { + if ('' === $locale) { + return false; + } + + $parts = preg_split('/[_-]/', $locale); + $language = strtolower($parts[0]); + + foreach ($parts as $part) { + if (4 === \strlen($part) && ctype_alpha($part)) { + return isset(self::RTL_SCRIPTS[ucfirst(strtolower($part))]); + } + } + + return isset(self::LANG_TO_SCRIPT[$language]) && isset(self::RTL_SCRIPTS[self::LANG_TO_SCRIPT[$language]]); + } } diff --git a/lib/symfony/polyfill-intl-icu/NumberFormatter.php b/lib/symfony/polyfill-intl-icu/NumberFormatter.php index cec375db7..9c8193d19 100644 --- a/lib/symfony/polyfill-intl-icu/NumberFormatter.php +++ b/lib/symfony/polyfill-intl-icu/NumberFormatter.php @@ -261,7 +261,7 @@ abstract class NumberFormatter } if (!\in_array($style, self::$supportedStyles)) { - $message = sprintf('The available styles are: %s.', implode(', ', array_keys(self::$supportedStyles))); + $message = \sprintf('The available styles are: %s.', implode(', ', array_keys(self::$supportedStyles))); throw new MethodArgumentValueNotImplementedException(__METHOD__, 'style', $style, $message); } @@ -352,7 +352,7 @@ abstract class NumberFormatter // The original NumberFormatter does not support this format type if (self::TYPE_CURRENCY === $type) { if (\PHP_VERSION_ID >= 80000) { - throw new \ValueError(sprintf('The format type must be a NumberFormatter::TYPE_* constant (%s given).', $type)); + throw new \ValueError(\sprintf('The format type must be a NumberFormatter::TYPE_* constant (%s given).', $type)); } trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING); @@ -361,7 +361,7 @@ abstract class NumberFormatter } if (self::CURRENCY === $this->style) { - throw new NotImplementedException(sprintf('"%s()" method does not support the formatting of currencies (instance with CURRENCY style). "%s".', __METHOD__, NotImplementedException::INTL_INSTALL_MESSAGE)); + throw new NotImplementedException(\sprintf('"%s()" method does not support the formatting of currencies (instance with CURRENCY style). "%s".', __METHOD__, NotImplementedException::INTL_INSTALL_MESSAGE)); } // Only the default type is supported. @@ -496,7 +496,7 @@ abstract class NumberFormatter { if (self::TYPE_DEFAULT === $type || self::TYPE_CURRENCY === $type) { if (\PHP_VERSION_ID >= 80000) { - throw new \ValueError(sprintf('The format type must be a NumberFormatter::TYPE_* constant (%d given).', $type)); + throw new \ValueError(\sprintf('The format type must be a NumberFormatter::TYPE_* constant (%d given).', $type)); } trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING); @@ -553,7 +553,7 @@ abstract class NumberFormatter public function setAttribute(int $attribute, $value) { if (!\in_array($attribute, self::$supportedAttributes)) { - $message = sprintf( + $message = \sprintf( 'The available attributes are: %s', implode(', ', array_keys(self::$supportedAttributes)) ); @@ -562,7 +562,7 @@ abstract class NumberFormatter } if (self::$supportedAttributes['ROUNDING_MODE'] === $attribute && $this->isInvalidRoundingMode($value)) { - $message = sprintf( + $message = \sprintf( 'The supported values for ROUNDING_MODE are: %s', implode(', ', array_keys(self::$roundingModes)) ); diff --git a/lib/symfony/polyfill-intl-icu/README.md b/lib/symfony/polyfill-intl-icu/README.md index b7faedc5d..0ac69a00b 100644 --- a/lib/symfony/polyfill-intl-icu/README.md +++ b/lib/symfony/polyfill-intl-icu/README.md @@ -13,6 +13,7 @@ It is limited to the "en" locale and to: - [`NumberFormatter`](https://php.net/NumberFormatter) - [`Locale`](https://php.net/Locale) - [`IntlDateFormatter`](https://php.net/IntlDateFormatter) +- [`IntlListFormatter`](https://php.net/IntlListFormatter) More information can be found in the [main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). diff --git a/lib/symfony/polyfill-intl-icu/Resources/stubs/IntlListFormatter.php b/lib/symfony/polyfill-intl-icu/Resources/stubs/IntlListFormatter.php new file mode 100644 index 000000000..ba7807203 --- /dev/null +++ b/lib/symfony/polyfill-intl-icu/Resources/stubs/IntlListFormatter.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Icu\IntlListFormatter as IntlListFormatterPolyfill; + +/** + * Stub implementation for the IntlListFormatter class of the intl extension. + * + * @author Ayesh Karunaratne + */ +final class IntlListFormatter extends IntlListFormatterPolyfill +{ +} diff --git a/lib/symfony/polyfill-mbstring/Mbstring.php b/lib/symfony/polyfill-mbstring/Mbstring.php index 31e36a368..7f256360b 100644 --- a/lib/symfony/polyfill-mbstring/Mbstring.php +++ b/lib/symfony/polyfill-mbstring/Mbstring.php @@ -133,7 +133,7 @@ final class Mbstring public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars) { $ok = true; - array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) { + array_walk_recursive($vars, static function (&$v) use (&$ok, $toEncoding, $fromEncoding) { if (false === $v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding)) { $ok = false; } @@ -194,7 +194,7 @@ final class Mbstring $convmap[$i + 1] += $convmap[$i + 2]; } - $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use ($cnt, $convmap) { + $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))'.(\PHP_VERSION_ID >= 80200 ? '' : '(?!&)').';?/', static function (array $m) use ($cnt, $convmap) { $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1]; for ($i = 0; $i < $cnt; $i += 4) { if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) { @@ -268,7 +268,7 @@ final class Mbstring for ($j = 0; $j < $cnt; $j += 4) { if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) { $cOffset = ($c + $convmap[$j + 2]) & $convmap[$j + 3]; - $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; + $result .= $is_hex ? \sprintf('&#x%X;', $cOffset) : '&#'.$cOffset.';'; continue 2; } } @@ -382,7 +382,7 @@ final class Mbstring return false; } - throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding)); + throw new \ValueError(\sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding)); } public static function mb_language($lang = null) @@ -403,7 +403,7 @@ final class Mbstring return false; } - throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang)); + throw new \ValueError(\sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang)); } public static function mb_list_encodings() @@ -834,19 +834,32 @@ final class Mbstring return $code; } - public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null): string + /** @return string|false */ + public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null) { if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) { + if (\PHP_VERSION_ID < 80000) { + trigger_error('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH', \E_USER_WARNING); + + return false; + } + throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH'); } if (null === $encoding) { $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given'); + } elseif (!self::assertEncoding($encoding, 'mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given')) { + return false; } if (self::mb_strlen($pad_string, $encoding) <= 0) { + if (\PHP_VERSION_ID < 80000) { + trigger_error('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string', \E_USER_WARNING); + + return false; + } + throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'); } @@ -869,12 +882,13 @@ final class Mbstring } } - public static function mb_ucfirst(string $string, ?string $encoding = null): string + /** @return string|false */ + public static function mb_ucfirst(string $string, ?string $encoding = null) { if (null === $encoding) { $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); + } elseif (!self::assertEncoding($encoding, 'mb_ucfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) { + return false; } $firstChar = mb_substr($string, 0, 1, $encoding); @@ -883,12 +897,13 @@ final class Mbstring return $firstChar.mb_substr($string, 1, null, $encoding); } - public static function mb_lcfirst(string $string, ?string $encoding = null): string + /** @return string|false */ + public static function mb_lcfirst(string $string, ?string $encoding = null) { if (null === $encoding) { $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given'); + } elseif (!self::assertEncoding($encoding, 'mb_lcfirst(): Argument #2 ($encoding) must be a valid encoding, "%s" given')) { + return false; } $firstChar = mb_substr($string, 0, 1, $encoding); @@ -968,30 +983,42 @@ final class Mbstring return 'UTF-8'; } + if ('UTF-32' === $encoding) { + return 'UTF-32BE'; + } + + if ('UTF-16' === $encoding) { + return 'UTF-16BE'; + } + return $encoding; } - public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string + /** @return string|false */ + public static function mb_trim(string $string, ?string $characters = null, ?string $encoding = null) { return self::mb_internal_trim('{^[%s]+|[%1$s]+$}Du', $string, $characters, $encoding, __FUNCTION__); } - public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string + /** @return string|false */ + public static function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null) { return self::mb_internal_trim('{^[%s]+}Du', $string, $characters, $encoding, __FUNCTION__); } - public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string + /** @return string|false */ + public static function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null) { return self::mb_internal_trim('{[%s]+$}Du', $string, $characters, $encoding, __FUNCTION__); } - private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function): string + /** @return string|false */ + private static function mb_internal_trim(string $regex, string $string, ?string $characters, ?string $encoding, string $function) { if (null === $encoding) { $encoding = self::mb_internal_encoding(); - } else { - self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given'); + } elseif (!self::assertEncoding($encoding, $function.'(): Argument #3 ($encoding) must be a valid encoding, "%s" given')) { + return false; } if ('' === $characters) { @@ -1020,7 +1047,7 @@ final class Mbstring $characters = preg_quote($characters); } - $string = preg_replace(sprintf($regex, $characters), '', $string); + $string = preg_replace(\sprintf($regex, $characters), '', $string); if (null === $encoding) { return $string; @@ -1029,17 +1056,22 @@ final class Mbstring return iconv('UTF-8', $encoding.'//IGNORE', $string); } - private static function assertEncoding(string $encoding, string $errorFormat): void + private static function assertEncoding(string $encoding, string $errorFormat): bool { try { $validEncoding = @self::mb_check_encoding('', $encoding); } catch (\ValueError $e) { - throw new \ValueError(sprintf($errorFormat, $encoding)); + throw new \ValueError(\sprintf($errorFormat, $encoding)); } - // BC for PHP 7.3 and lower if (!$validEncoding) { - throw new \ValueError(sprintf($errorFormat, $encoding)); + if (80000 > \PHP_VERSION_ID) { + trigger_error(\sprintf($errorFormat, $encoding), \E_USER_WARNING); + } else { + throw new \ValueError(\sprintf($errorFormat, $encoding)); + } } + + return $validEncoding; } } diff --git a/lib/symfony/polyfill-mbstring/bootstrap.php b/lib/symfony/polyfill-mbstring/bootstrap.php index ff51ae079..df3d9f3d4 100644 --- a/lib/symfony/polyfill-mbstring/bootstrap.php +++ b/lib/symfony/polyfill-mbstring/bootstrap.php @@ -133,30 +133,29 @@ if (!function_exists('mb_str_split')) { } if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } + function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null) { return p\Mbstring::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } } if (!function_exists('mb_ucfirst')) { - function mb_ucfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_ucfirst($string, $encoding); } + function mb_ucfirst(string $string, ?string $encoding = null) { return p\Mbstring::mb_ucfirst($string, $encoding); } } if (!function_exists('mb_lcfirst')) { - function mb_lcfirst(string $string, ?string $encoding = null): string { return p\Mbstring::mb_lcfirst($string, $encoding); } + function mb_lcfirst(string $string, ?string $encoding = null) { return p\Mbstring::mb_lcfirst($string, $encoding); } } if (!function_exists('mb_trim')) { - function mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_trim($string, $characters, $encoding); } + function mb_trim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_trim($string, $characters, $encoding); } } if (!function_exists('mb_ltrim')) { - function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } + function mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_ltrim($string, $characters, $encoding); } } if (!function_exists('mb_rtrim')) { - function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } + function mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null) { return p\Mbstring::mb_rtrim($string, $characters, $encoding); } } - if (extension_loaded('mbstring')) { return; } diff --git a/lib/symfony/polyfill-php83/Php83.php b/lib/symfony/polyfill-php83/Php83.php index 8b7ee4c70..03409fb0c 100644 --- a/lib/symfony/polyfill-php83/Php83.php +++ b/lib/symfony/polyfill-php83/Php83.php @@ -32,7 +32,7 @@ final class Php83 } if ($depth > self::JSON_MAX_DEPTH) { - throw new \ValueError(sprintf('json_validate(): Argument #2 ($depth) must be less than %d', self::JSON_MAX_DEPTH)); + throw new \ValueError(\sprintf('json_validate(): Argument #2 ($depth) must be less than %d', self::JSON_MAX_DEPTH)); } json_decode($json, true, $depth, $flags); @@ -40,7 +40,8 @@ final class Php83 return \JSON_ERROR_NONE === json_last_error(); } - public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null): string + /** @return string|false */ + public static function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = \STR_PAD_RIGHT, ?string $encoding = null) { if (!\in_array($pad_type, [\STR_PAD_RIGHT, \STR_PAD_LEFT, \STR_PAD_BOTH], true)) { throw new \ValueError('mb_str_pad(): Argument #4 ($pad_type) must be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH'); @@ -50,19 +51,27 @@ final class Php83 $encoding = mb_internal_encoding(); } + $errorToTrigger = null; try { - $validEncoding = @mb_check_encoding('', $encoding); + if (!@mb_check_encoding('', $encoding)) { + $errorToTrigger = \sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding); + } } catch (\ValueError $e) { - throw new \ValueError(sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding)); - } - - // BC for PHP 7.3 and lower - if (!$validEncoding) { - throw new \ValueError(sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding)); + $errorToTrigger = \sprintf('mb_str_pad(): Argument #5 ($encoding) must be a valid encoding, "%s" given', $encoding); } if (mb_strlen($pad_string, $encoding) <= 0) { - throw new \ValueError('mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'); + $errorToTrigger = 'mb_str_pad(): Argument #3 ($pad_string) must be a non-empty string'; + } + + if (null !== $errorToTrigger) { + if (80000 > \PHP_VERSION_ID) { + trigger_error($errorToTrigger, \E_USER_WARNING); + + return false; + } + + throw new \ValueError($errorToTrigger); } $paddingRequired = $length - mb_strlen($string, $encoding); @@ -135,7 +144,7 @@ final class Php83 } if (preg_match('/\A(?:0[aA0]?|[aA])\z/', $string)) { - throw new \ValueError(sprintf('str_decrement(): Argument #1 ($string) "%s" is out of decrement range', $string)); + throw new \ValueError(\sprintf('str_decrement(): Argument #1 ($string) "%s" is out of decrement range', $string)); } if (!\in_array(substr($string, -1), ['A', 'a', '0'], true)) { diff --git a/lib/symfony/polyfill-php83/bootstrap.php b/lib/symfony/polyfill-php83/bootstrap.php index a92799cb3..8d721a29c 100644 --- a/lib/symfony/polyfill-php83/bootstrap.php +++ b/lib/symfony/polyfill-php83/bootstrap.php @@ -19,12 +19,6 @@ if (!function_exists('json_validate')) { function json_validate(string $json, int $depth = 512, int $flags = 0): bool { return p\Php83::json_validate($json, $depth, $flags); } } -if (extension_loaded('mbstring')) { - if (!function_exists('mb_str_pad')) { - function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Php83::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } - } -} - if (!function_exists('stream_context_set_options')) { function stream_context_set_options($context, array $options): bool { return stream_context_set_option($context, $options); } } @@ -37,8 +31,14 @@ if (!function_exists('str_decrement')) { function str_decrement(string $string): string { return p\Php83::str_decrement($string); } } -if (\PHP_VERSION_ID >= 80100) { - return require __DIR__.'/bootstrap81.php'; +if (\PHP_VERSION_ID >= 80000) { + return require __DIR__.'/bootstrap80.php'; +} + +if (extension_loaded('mbstring')) { + if (!function_exists('mb_str_pad')) { + function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null) { return p\Php83::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } + } } if (!function_exists('ldap_exop_sync') && function_exists('ldap_exop')) { diff --git a/lib/symfony/polyfill-php83/bootstrap80.php b/lib/symfony/polyfill-php83/bootstrap80.php new file mode 100644 index 000000000..9b812d024 --- /dev/null +++ b/lib/symfony/polyfill-php83/bootstrap80.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php83 as p; + +if (extension_loaded('mbstring')) { + if (!function_exists('mb_str_pad')) { + function mb_str_pad(string $string, int $length, string $pad_string = ' ', int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string { return p\Php83::mb_str_pad($string, $length, $pad_string, $pad_type, $encoding); } + } +} + +if (\PHP_VERSION_ID >= 80100) { + return require __DIR__.'/bootstrap81.php'; +} + +if (!function_exists('ldap_exop_sync') && function_exists('ldap_exop')) { + function ldap_exop_sync($ldap, string $request_oid, ?string $request_data = null, ?array $controls = null, &$response_data = null, &$response_oid = null): bool { return ldap_exop($ldap, $request_oid, $request_data, $controls, $response_data, $response_oid); } +} + +if (!function_exists('ldap_connect_wallet') && function_exists('ldap_connect')) { + function ldap_connect_wallet(?string $uri, string $wallet, string $password, int $auth_mode = \GSLC_SSL_NO_AUTH) { return ldap_connect($uri, $wallet, $password, $auth_mode); } +} diff --git a/lib/symfony/runtime/CHANGELOG.md b/lib/symfony/runtime/CHANGELOG.md new file mode 100644 index 000000000..1a608b4cf --- /dev/null +++ b/lib/symfony/runtime/CHANGELOG.md @@ -0,0 +1,19 @@ +CHANGELOG +========= + +6.4 +--- + + * Add argument `bool $debug = false` to `HttpKernelRunner::__construct()` + +5.4 +--- + + * The component is not experimental anymore + * Add options "env_var_name" and "debug_var_name" to `GenericRuntime` and `SymfonyRuntime` + * Add option "dotenv_overload" to `SymfonyRuntime` + +5.3.0 +----- + + * Add the component diff --git a/lib/symfony/runtime/GenericRuntime.php b/lib/symfony/runtime/GenericRuntime.php new file mode 100644 index 000000000..b432630d1 --- /dev/null +++ b/lib/symfony/runtime/GenericRuntime.php @@ -0,0 +1,223 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +use Symfony\Component\Runtime\Internal\BasicErrorHandler; +use Symfony\Component\Runtime\Resolver\ClosureResolver; +use Symfony\Component\Runtime\Resolver\DebugClosureResolver; +use Symfony\Component\Runtime\Runner\ClosureRunner; + +// Help opcache.preload discover always-needed symbols +class_exists(ClosureResolver::class); + +/** + * A runtime to do bare-metal PHP without using superglobals. + * + * It supports the following options: + * - "debug" toggles displaying errors and defaults + * to the "APP_DEBUG" environment variable; + * - "runtimes" maps types to a GenericRuntime implementation + * that knows how to deal with each of them; + * - "error_handler" defines the class to use to handle PHP errors; + * - "env_var_name" and "debug_var_name" define the name of the env + * vars that hold the Symfony env and the debug flag respectively. + * + * The app-callable can declare arguments among either: + * - "array $context" to get a local array similar to $_SERVER; + * - "array $argv" to get the command line arguments when running on the CLI; + * - "array $request" to get a local array with keys "query", "body", "files" and + * "session", which map to $_GET, $_POST, $FILES and &$_SESSION respectively. + * + * It should return a Closure():int|string|null or an instance of RunnerInterface. + * + * In debug mode, the runtime registers a strict error handler + * that throws exceptions when a PHP warning/notice is raised. + * + * @author Nicolas Grekas + */ +class GenericRuntime implements RuntimeInterface +{ + protected $options; + + /** + * @param array { + * debug?: ?bool, + * runtimes?: ?array, + * error_handler?: string|false, + * env_var_name?: string, + * debug_var_name?: string, + * } $options + */ + public function __construct(array $options = []) + { + $options['env_var_name'] ??= 'APP_ENV'; + $debugKey = $options['debug_var_name'] ??= 'APP_DEBUG'; + + $debug = $options['debug'] ?? $_SERVER[$debugKey] ?? $_ENV[$debugKey] ?? true; + + if (!\is_bool($debug)) { + $debug = filter_var($debug, \FILTER_VALIDATE_BOOL); + } + + if ($debug) { + umask(0000); + $_SERVER[$debugKey] = $_ENV[$debugKey] = '1'; + } else { + $_SERVER[$debugKey] = $_ENV[$debugKey] = '0'; + } + + if (false !== $errorHandler = ($options['error_handler'] ?? BasicErrorHandler::class)) { + $errorHandler::register($debug); + $options['error_handler'] = false; + } + + $this->options = $options; + } + + public function getResolver(callable $callable, ?\ReflectionFunction $reflector = null): ResolverInterface + { + $callable = $callable(...); + $parameters = ($reflector ?? new \ReflectionFunction($callable))->getParameters(); + $arguments = function () use ($parameters) { + $arguments = []; + + try { + foreach ($parameters as $parameter) { + $type = $parameter->getType(); + $arguments[] = $this->getArgument($parameter, $type instanceof \ReflectionNamedType ? $type->getName() : null); + } + } catch (\InvalidArgumentException $e) { + if (!$parameter->isOptional()) { + throw $e; + } + } + + return $arguments; + }; + + if ($_SERVER[$this->options['debug_var_name']]) { + return new DebugClosureResolver($callable, $arguments); + } + + return new ClosureResolver($callable, $arguments); + } + + public function getRunner(?object $application): RunnerInterface + { + $application ??= static fn () => 0; + + if ($application instanceof RunnerInterface) { + return $application; + } + + if (!$application instanceof \Closure) { + if ($runtime = $this->resolveRuntime($application::class)) { + return $runtime->getRunner($application); + } + + if (!\is_callable($application)) { + throw new \LogicException(\sprintf('"%s" doesn\'t know how to handle apps of type "%s".', get_debug_type($this), get_debug_type($application))); + } + + $application = $application(...); + } + + if ($_SERVER[$this->options['debug_var_name']] && ($r = new \ReflectionFunction($application)) && $r->getNumberOfRequiredParameters()) { + throw new \ArgumentCountError(\sprintf('Zero argument should be required by the runner callable, but at least one is in "%s" on line "%d.', $r->getFileName(), $r->getStartLine())); + } + + return new ClosureRunner($application); + } + + protected function getArgument(\ReflectionParameter $parameter, ?string $type): mixed + { + if ('array' === $type) { + switch ($parameter->name) { + case 'context': + $context = $_SERVER; + + if ($_ENV && !isset($_SERVER['PATH']) && !isset($_SERVER['Path'])) { + $context += $_ENV; + } + + return $context; + + case 'argv': + return $_SERVER['argv'] ?? []; + + case 'request': + return [ + 'query' => $_GET, + 'body' => $_POST, + 'files' => $_FILES, + 'session' => &$_SESSION, + ]; + } + } + + if (RuntimeInterface::class === $type) { + return $this; + } + + if (!$runtime = $this->getRuntime($type)) { + $r = $parameter->getDeclaringFunction(); + + throw new \InvalidArgumentException(\sprintf('Cannot resolve argument "%s $%s" in "%s" on line "%d": "%s" supports only arguments "array $context", "array $argv" and "array $request", or a runtime named "Symfony\Runtime\%1$sRuntime".', $type, $parameter->name, $r->getFileName(), $r->getStartLine(), get_debug_type($this))); + } + + return $runtime->getArgument($parameter, $type); + } + + protected static function register(self $runtime): self + { + return $runtime; + } + + private function getRuntime(string $type): ?self + { + if (null === $runtime = ($this->options['runtimes'][$type] ?? null)) { + $runtime = 'Symfony\Runtime\\'.$type.'Runtime'; + $runtime = class_exists($runtime) ? $runtime : $this->options['runtimes'][$type] = false; + } + + if (\is_string($runtime)) { + $runtime = $runtime::register($this); + } + + if ($this === $runtime) { + return null; + } + + return $runtime ?: null; + } + + private function resolveRuntime(string $class): ?self + { + if ($runtime = $this->getRuntime($class)) { + return $runtime; + } + + foreach (class_parents($class) as $type) { + if ($runtime = $this->getRuntime($type)) { + return $runtime; + } + } + + foreach (class_implements($class) as $type) { + if ($runtime = $this->getRuntime($type)) { + return $runtime; + } + } + + return null; + } +} diff --git a/lib/symfony/runtime/Internal/BasicErrorHandler.php b/lib/symfony/runtime/Internal/BasicErrorHandler.php new file mode 100644 index 000000000..c0c290e68 --- /dev/null +++ b/lib/symfony/runtime/Internal/BasicErrorHandler.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Internal; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class BasicErrorHandler +{ + public static function register(bool $debug): void + { + error_reporting(\E_ALL & ~\E_DEPRECATED & ~\E_USER_DEPRECATED); + + if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { + ini_set('display_errors', $debug); + } elseif (!filter_var(\ini_get('log_errors'), \FILTER_VALIDATE_BOOL) || \ini_get('error_log')) { + // CLI - display errors only if they're not already logged to STDERR + ini_set('display_errors', 1); + } + + if (0 <= \ini_get('zend.assertions')) { + ini_set('zend.assertions', (int) $debug); + } + ini_set('assert.active', 1); + ini_set('assert.exception', 1); + + set_error_handler(new self()); + } + + public function __invoke(int $type, string $message, string $file, int $line): bool + { + if ((\E_DEPRECATED | \E_USER_DEPRECATED) & $type) { + return true; + } + + if ((error_reporting() | \E_ERROR | \E_RECOVERABLE_ERROR | \E_PARSE | \E_CORE_ERROR | \E_COMPILE_ERROR | \E_USER_ERROR) & $type) { + throw new \ErrorException($message, 0, $type, $file, $line); + } + + return false; + } +} diff --git a/lib/symfony/runtime/Internal/ComposerPlugin.php b/lib/symfony/runtime/Internal/ComposerPlugin.php new file mode 100644 index 000000000..cad8d85fc --- /dev/null +++ b/lib/symfony/runtime/Internal/ComposerPlugin.php @@ -0,0 +1,119 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Internal; + +use Composer\Composer; +use Composer\EventDispatcher\EventSubscriberInterface; +use Composer\Factory; +use Composer\IO\IOInterface; +use Composer\Plugin\PluginInterface; +use Composer\Script\ScriptEvents; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class ComposerPlugin implements PluginInterface, EventSubscriberInterface +{ + private Composer $composer; + private IOInterface $io; + + private static bool $activated = false; + + public function activate(Composer $composer, IOInterface $io): void + { + self::$activated = true; + $this->composer = $composer; + $this->io = $io; + } + + public function deactivate(Composer $composer, IOInterface $io): void + { + self::$activated = false; + } + + public function uninstall(Composer $composer, IOInterface $io): void + { + @unlink($composer->getConfig()->get('vendor-dir').'/autoload_runtime.php'); + } + + public function updateAutoloadFile(): void + { + $vendorDir = realpath($this->composer->getConfig()->get('vendor-dir')); + + if (!is_file($autoloadFile = $vendorDir.'/autoload.php') + || false === $extra = $this->composer->getPackage()->getExtra()['runtime'] ?? [] + ) { + return; + } + + $fs = new Filesystem(); + $projectDir = \dirname(realpath(Factory::getComposerFile())); + + if (null === $autoloadTemplate = $extra['autoload_template'] ?? null) { + $autoloadTemplate = __DIR__.'/autoload_runtime.template'; + } else { + if (!$fs->isAbsolutePath($autoloadTemplate)) { + $autoloadTemplate = $projectDir.'/'.$autoloadTemplate; + } + + if (!is_file($autoloadTemplate)) { + throw new \InvalidArgumentException(\sprintf('File "%s" defined under "extra.runtime.autoload_template" in your composer.json file not found.', $this->composer->getPackage()->getExtra()['runtime']['autoload_template'])); + } + } + + $projectDir = $fs->makePathRelative($projectDir, $vendorDir); + $nestingLevel = 0; + + while (str_starts_with($projectDir, '../')) { + ++$nestingLevel; + $projectDir = substr($projectDir, 3); + } + + if (!$nestingLevel) { + $projectDir = '__'.'DIR__.'.var_export('/'.$projectDir, true); + } else { + $projectDir = 'dirname(__'."DIR__, $nestingLevel)".('' !== $projectDir ? '.'.var_export('/'.$projectDir, true) : ''); + } + + $runtimeClass = $extra['class'] ?? SymfonyRuntime::class; + + unset($extra['class'], $extra['autoload_template']); + + $code = strtr(file_get_contents($autoloadTemplate), [ + '%project_dir%' => $projectDir, + '%runtime_class%' => var_export($runtimeClass, true), + '%runtime_options%' => '['.substr(var_export($extra, true), 7, -1)." 'project_dir' => {$projectDir},\n]", + ]); + + // could use Composer\Util\Filesystem::filePutContentsIfModified once Composer 1.x support is dropped for this plugin + $path = substr_replace($autoloadFile, '_runtime', -4, 0); + $currentContent = @file_exists($path) ? @file_get_contents($path) : false; + if (false === $currentContent || $currentContent !== $code) { + file_put_contents($path, $code); + } + } + + public static function getSubscribedEvents(): array + { + if (!self::$activated) { + return []; + } + + return [ + ScriptEvents::POST_AUTOLOAD_DUMP => 'updateAutoloadFile', + ]; + } +} diff --git a/lib/symfony/runtime/Internal/Console/ApplicationRuntime.php b/lib/symfony/runtime/Internal/Console/ApplicationRuntime.php new file mode 100644 index 000000000..de6b1d974 --- /dev/null +++ b/lib/symfony/runtime/Internal/Console/ApplicationRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\Console; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class ApplicationRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/Console/Command/CommandRuntime.php b/lib/symfony/runtime/Internal/Console/Command/CommandRuntime.php new file mode 100644 index 000000000..9cc198ea1 --- /dev/null +++ b/lib/symfony/runtime/Internal/Console/Command/CommandRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\Console\Command; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class CommandRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php b/lib/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php new file mode 100644 index 000000000..44360bf50 --- /dev/null +++ b/lib/symfony/runtime/Internal/Console/Input/InputInterfaceRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\Console\Input; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class InputInterfaceRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php b/lib/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php new file mode 100644 index 000000000..7c59186ad --- /dev/null +++ b/lib/symfony/runtime/Internal/Console/Output/OutputInterfaceRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\Console\Output; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class OutputInterfaceRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php b/lib/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php new file mode 100644 index 000000000..2a3a0bb82 --- /dev/null +++ b/lib/symfony/runtime/Internal/HttpFoundation/RequestRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\HttpFoundation; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class RequestRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php b/lib/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php new file mode 100644 index 000000000..c70fbfff5 --- /dev/null +++ b/lib/symfony/runtime/Internal/HttpFoundation/ResponseRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\HttpFoundation; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class ResponseRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php b/lib/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php new file mode 100644 index 000000000..08601abff --- /dev/null +++ b/lib/symfony/runtime/Internal/HttpKernel/HttpKernelInterfaceRuntime.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Runtime\Symfony\Component\HttpKernel; + +use Symfony\Component\Runtime\SymfonyRuntime; + +/** + * @internal + */ +class HttpKernelInterfaceRuntime extends SymfonyRuntime +{ +} diff --git a/lib/symfony/runtime/Internal/MissingDotenv.php b/lib/symfony/runtime/Internal/MissingDotenv.php new file mode 100644 index 000000000..896865653 --- /dev/null +++ b/lib/symfony/runtime/Internal/MissingDotenv.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Internal; + +/** + * @internal class that should be loaded only when symfony/dotenv is not installed + */ +class MissingDotenv +{ +} diff --git a/lib/symfony/runtime/Internal/SymfonyErrorHandler.php b/lib/symfony/runtime/Internal/SymfonyErrorHandler.php new file mode 100644 index 000000000..47c67605b --- /dev/null +++ b/lib/symfony/runtime/Internal/SymfonyErrorHandler.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Internal; + +use Symfony\Component\ErrorHandler\BufferingLogger; +use Symfony\Component\ErrorHandler\DebugClassLoader; +use Symfony\Component\ErrorHandler\ErrorHandler; + +/** + * @author Nicolas Grekas + * + * @internal + */ +class SymfonyErrorHandler +{ + public static function register(bool $debug): void + { + if (!class_exists(ErrorHandler::class)) { + BasicErrorHandler::register($debug); + + return; + } + + error_reporting(\E_ALL & ~\E_DEPRECATED & ~\E_USER_DEPRECATED); + + if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { + ini_set('display_errors', $debug); + } elseif (!filter_var(\ini_get('log_errors'), \FILTER_VALIDATE_BOOL) || \ini_get('error_log')) { + // CLI - display errors only if they're not already logged to STDERR + ini_set('display_errors', 1); + } + + if (0 <= \ini_get('zend.assertions')) { + ini_set('zend.assertions', (int) $debug); + } + ini_set('assert.active', 1); + ini_set('assert.exception', 1); + + if ($debug) { + DebugClassLoader::enable(); + } + + ErrorHandler::register(new ErrorHandler(new BufferingLogger(), $debug)); + } +} diff --git a/lib/symfony/runtime/Internal/autoload_runtime.template b/lib/symfony/runtime/Internal/autoload_runtime.template new file mode 100644 index 000000000..68af94593 --- /dev/null +++ b/lib/symfony/runtime/Internal/autoload_runtime.template @@ -0,0 +1,28 @@ +getResolver($app) + ->resolve(); + +$app = $app(...$args); + +exit( + $runtime + ->getRunner($app) + ->run() +); diff --git a/lib/symfony/runtime/LICENSE b/lib/symfony/runtime/LICENSE new file mode 100644 index 000000000..99c6bdf35 --- /dev/null +++ b/lib/symfony/runtime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2021-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/symfony/runtime/README.md b/lib/symfony/runtime/README.md new file mode 100644 index 000000000..006e7a22c --- /dev/null +++ b/lib/symfony/runtime/README.md @@ -0,0 +1,13 @@ +Runtime Component +================= + +Symfony Runtime enables decoupling applications from global state. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/runtime.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/lib/symfony/runtime/Resolver/ClosureResolver.php b/lib/symfony/runtime/Resolver/ClosureResolver.php new file mode 100644 index 000000000..c58cf2fbf --- /dev/null +++ b/lib/symfony/runtime/Resolver/ClosureResolver.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\Component\Runtime\Resolver; + +use Symfony\Component\Runtime\ResolverInterface; + +/** + * @author Nicolas Grekas + */ +class ClosureResolver implements ResolverInterface +{ + public function __construct( + private readonly \Closure $closure, + private readonly \Closure $arguments, + ) { + } + + public function resolve(): array + { + return [$this->closure, ($this->arguments)()]; + } +} diff --git a/lib/symfony/runtime/Resolver/DebugClosureResolver.php b/lib/symfony/runtime/Resolver/DebugClosureResolver.php new file mode 100644 index 000000000..026b2731b --- /dev/null +++ b/lib/symfony/runtime/Resolver/DebugClosureResolver.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\Runtime\Resolver; + +/** + * @author Nicolas Grekas + */ +class DebugClosureResolver extends ClosureResolver +{ + public function resolve(): array + { + [$closure, $arguments] = parent::resolve(); + + return [ + static function (...$arguments) use ($closure) { + if (\is_object($app = $closure(...$arguments)) || null === $app) { + return $app; + } + + $r = new \ReflectionFunction($closure); + + throw new \TypeError(\sprintf('Unexpected value of type "%s" returned, "object" expected from "%s" on line "%d".', get_debug_type($app), $r->getFileName(), $r->getStartLine())); + }, + $arguments, + ]; + } +} diff --git a/lib/symfony/runtime/ResolverInterface.php b/lib/symfony/runtime/ResolverInterface.php new file mode 100644 index 000000000..f6fa5980e --- /dev/null +++ b/lib/symfony/runtime/ResolverInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +/** + * @author Nicolas Grekas + */ +interface ResolverInterface +{ + /** + * @return array{0: callable, 1: mixed[]} + */ + public function resolve(): array; +} diff --git a/lib/symfony/runtime/Runner/ClosureRunner.php b/lib/symfony/runtime/Runner/ClosureRunner.php new file mode 100644 index 000000000..2b54f5a32 --- /dev/null +++ b/lib/symfony/runtime/Runner/ClosureRunner.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Runner; + +use Symfony\Component\Runtime\RunnerInterface; + +/** + * @author Nicolas Grekas + */ +class ClosureRunner implements RunnerInterface +{ + public function __construct( + private readonly \Closure $closure, + ) { + } + + public function run(): int + { + $exitStatus = ($this->closure)(); + + if (\is_string($exitStatus)) { + echo $exitStatus; + + return 0; + } + + if (null !== $exitStatus && !\is_int($exitStatus)) { + $r = new \ReflectionFunction($this->closure); + + throw new \TypeError(\sprintf('Unexpected value of type "%s" returned, "string|int|null" expected from "%s" on line "%d".', get_debug_type($exitStatus), $r->getFileName(), $r->getStartLine())); + } + + return $exitStatus ?? 0; + } +} diff --git a/lib/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php b/lib/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php new file mode 100644 index 000000000..d64bc1c77 --- /dev/null +++ b/lib/symfony/runtime/Runner/Symfony/ConsoleApplicationRunner.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Runner\Symfony; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Runtime\RunnerInterface; + +/** + * @author Nicolas Grekas + */ +class ConsoleApplicationRunner implements RunnerInterface +{ + public function __construct( + private readonly Application $application, + private readonly ?string $defaultEnv, + private readonly InputInterface $input, + private readonly ?OutputInterface $output = null, + ) { + } + + public function run(): int + { + if (null === $this->defaultEnv) { + return $this->application->run($this->input, $this->output); + } + + $definition = $this->application->getDefinition(); + + if (!$definition->hasOption('env') && !$definition->hasOption('e') && !$definition->hasShortcut('e')) { + $definition->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'The Environment name.', $this->defaultEnv)); + } + + if (!$definition->hasOption('no-debug')) { + $definition->addOption(new InputOption('--no-debug', null, InputOption::VALUE_NONE, 'Switches off debug mode.')); + } + + return $this->application->run($this->input, $this->output); + } +} diff --git a/lib/symfony/runtime/Runner/Symfony/HttpKernelRunner.php b/lib/symfony/runtime/Runner/Symfony/HttpKernelRunner.php new file mode 100644 index 000000000..13c9037ca --- /dev/null +++ b/lib/symfony/runtime/Runner/Symfony/HttpKernelRunner.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Runner\Symfony; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\TerminableInterface; +use Symfony\Component\Runtime\RunnerInterface; + +/** + * @author Nicolas Grekas + */ +class HttpKernelRunner implements RunnerInterface +{ + public function __construct( + private readonly HttpKernelInterface $kernel, + private readonly Request $request, + private readonly bool $debug = false, + ) { + } + + public function run(): int + { + $response = $this->kernel->handle($this->request); + + if (Kernel::VERSION_ID >= 60400) { + $response->send(false); + + if (\function_exists('fastcgi_finish_request') && !$this->debug) { + fastcgi_finish_request(); + } elseif (\function_exists('litespeed_finish_request') && !$this->debug) { + litespeed_finish_request(); + } else { + Response::closeOutputBuffers(0, true); + flush(); + } + } else { + $response->send(); + } + + if ($this->kernel instanceof TerminableInterface) { + $this->kernel->terminate($this->request, $response); + } + + return 0; + } +} diff --git a/lib/symfony/runtime/Runner/Symfony/ResponseRunner.php b/lib/symfony/runtime/Runner/Symfony/ResponseRunner.php new file mode 100644 index 000000000..04e5a3fa1 --- /dev/null +++ b/lib/symfony/runtime/Runner/Symfony/ResponseRunner.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime\Runner\Symfony; + +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Runtime\RunnerInterface; + +/** + * @author Nicolas Grekas + */ +class ResponseRunner implements RunnerInterface +{ + public function __construct( + private readonly Response $response, + ) { + } + + public function run(): int + { + $this->response->send(); + + return 0; + } +} diff --git a/lib/symfony/runtime/RunnerInterface.php b/lib/symfony/runtime/RunnerInterface.php new file mode 100644 index 000000000..9001ff435 --- /dev/null +++ b/lib/symfony/runtime/RunnerInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +/** + * @author Nicolas Grekas + */ +interface RunnerInterface +{ + public function run(): int; +} diff --git a/lib/symfony/runtime/RuntimeInterface.php b/lib/symfony/runtime/RuntimeInterface.php new file mode 100644 index 000000000..f151757e9 --- /dev/null +++ b/lib/symfony/runtime/RuntimeInterface.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +/** + * Enables decoupling applications from global state. + * + * @author Nicolas Grekas + */ +interface RuntimeInterface +{ + /** + * Returns a resolver that should compute the arguments of a callable. + * + * The callable itself should return an object that represents the application to pass to the getRunner() method. + */ + public function getResolver(callable $callable, ?\ReflectionFunction $reflector = null): ResolverInterface; + + /** + * Returns a callable that knows how to run the passed object and that returns its exit status as int. + * + * The passed object is typically created by calling ResolverInterface::resolve(). + */ + public function getRunner(?object $application): RunnerInterface; +} diff --git a/lib/symfony/runtime/SymfonyRuntime.php b/lib/symfony/runtime/SymfonyRuntime.php new file mode 100644 index 000000000..a6e1cba73 --- /dev/null +++ b/lib/symfony/runtime/SymfonyRuntime.php @@ -0,0 +1,235 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Runtime; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Dotenv\Dotenv; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\Runtime\Internal\MissingDotenv; +use Symfony\Component\Runtime\Internal\SymfonyErrorHandler; +use Symfony\Component\Runtime\Runner\Symfony\ConsoleApplicationRunner; +use Symfony\Component\Runtime\Runner\Symfony\HttpKernelRunner; +use Symfony\Component\Runtime\Runner\Symfony\ResponseRunner; + +// Help opcache.preload discover always-needed symbols +class_exists(MissingDotenv::class, false) || class_exists(Dotenv::class) || class_exists(MissingDotenv::class); + +/** + * Knows the basic conventions to run Symfony apps. + * + * In addition to the options managed by GenericRuntime, it accepts the following options: + * - "env" to define the name of the environment the app runs in; + * - "disable_dotenv" to disable looking for .env files; + * - "dotenv_path" to define the path of dot-env files - defaults to ".env"; + * - "prod_envs" to define the names of the production envs - defaults to ["prod"]; + * - "test_envs" to define the names of the test envs - defaults to ["test"]; + * - "use_putenv" to tell Dotenv to set env vars using putenv() (NOT RECOMMENDED.) + * - "dotenv_overload" to tell Dotenv to override existing vars + * + * When the "debug" / "env" options are not defined, they will fallback to the + * "APP_DEBUG" / "APP_ENV" environment variables, and to the "--env|-e" / "--no-debug" + * command line arguments if "symfony/console" is installed. + * + * When the "symfony/dotenv" component is installed, .env files are loaded. + * When "symfony/error-handler" is installed, it is registered in debug mode. + * + * On top of the base arguments provided by GenericRuntime, + * this runtime can feed the app-callable with arguments of type: + * - Request from "symfony/http-foundation" if the component is installed; + * - Application, Command, InputInterface and/or OutputInterface + * from "symfony/console" if the component is installed. + * + * This runtime can handle app-callables that return instances of either: + * - HttpKernelInterface, + * - Response, + * - Application, + * - Command, + * - int|string|null as handled by GenericRuntime. + * + * @author Nicolas Grekas + */ +class SymfonyRuntime extends GenericRuntime +{ + private readonly ArgvInput $input; + private readonly ConsoleOutput $output; + private readonly Application $console; + private readonly Command $command; + private readonly Request $request; + + /** + * @param array { + * debug?: ?bool, + * env?: ?string, + * disable_dotenv?: ?bool, + * project_dir?: ?string, + * prod_envs?: ?string[], + * dotenv_path?: ?string, + * test_envs?: ?string[], + * use_putenv?: ?bool, + * runtimes?: ?array, + * error_handler?: string|false, + * env_var_name?: string, + * debug_var_name?: string, + * dotenv_overload?: ?bool, + * } $options + */ + public function __construct(array $options = []) + { + $envKey = $options['env_var_name'] ??= 'APP_ENV'; + $debugKey = $options['debug_var_name'] ??= 'APP_DEBUG'; + + if (isset($options['env'])) { + $_SERVER[$envKey] = $options['env']; + } elseif (empty($_GET) && isset($_SERVER['argv']) && class_exists(ArgvInput::class)) { + $this->options = $options; + $this->getInput(); + } + + if (!($options['disable_dotenv'] ?? false) && isset($options['project_dir']) && !class_exists(MissingDotenv::class, false)) { + (new Dotenv($envKey, $debugKey)) + ->setProdEnvs((array) ($options['prod_envs'] ?? ['prod'])) + ->usePutenv($options['use_putenv'] ?? false) + ->bootEnv($options['project_dir'].'/'.($options['dotenv_path'] ?? '.env'), 'dev', (array) ($options['test_envs'] ?? ['test']), $options['dotenv_overload'] ?? false); + + if (isset($this->input) && ($options['dotenv_overload'] ?? false)) { + if ($this->input->getParameterOption(['--env', '-e'], $_SERVER[$envKey], true) !== $_SERVER[$envKey]) { + throw new \LogicException(\sprintf('Cannot use "--env" or "-e" when the "%s" file defines "%s" and the "dotenv_overload" runtime option is true.', $options['dotenv_path'] ?? '.env', $envKey)); + } + + if ($_SERVER[$debugKey] && $this->input->hasParameterOption('--no-debug', true)) { + putenv($debugKey.'='.$_SERVER[$debugKey] = $_ENV[$debugKey] = '0'); + } + } + + $options['debug'] ??= '1' === $_SERVER[$debugKey]; + $options['disable_dotenv'] = true; + } else { + $_SERVER[$envKey] ??= $_ENV[$envKey] ?? 'dev'; + $_SERVER[$debugKey] ??= $_ENV[$debugKey] ?? !\in_array($_SERVER[$envKey], (array) ($options['prod_envs'] ?? ['prod']), true); + } + + $options['error_handler'] ??= SymfonyErrorHandler::class; + + parent::__construct($options); + } + + public function getRunner(?object $application): RunnerInterface + { + if ($application instanceof HttpKernelInterface) { + return new HttpKernelRunner($application, $this->request ??= Request::createFromGlobals(), $this->options['debug'] ?? false); + } + + if ($application instanceof Response) { + return new ResponseRunner($application); + } + + if ($application instanceof Command) { + $console = $this->console ??= new Application(); + $console->setName($application->getName() ?: $console->getName()); + + if (!$application->getName() || !$console->has($application->getName())) { + $application->setName($_SERVER['argv'][0]); + if (method_exists($console, 'addCommand')) { + $console->addCommand($application); + } else { + $console->add($application); + } + } + + $console->setDefaultCommand($application->getName(), true); + $console->getDefinition()->addOptions($application->getDefinition()->getOptions()); + + return $this->getRunner($console); + } + + if ($application instanceof Application) { + if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) { + echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.\PHP_SAPI.' SAPI'.\PHP_EOL; + } + + set_time_limit(0); + $defaultEnv = !isset($this->options['env']) ? ($_SERVER[$this->options['env_var_name']] ?? 'dev') : null; + $output = $this->output ??= new ConsoleOutput(); + + return new ConsoleApplicationRunner($application, $defaultEnv, $this->getInput(), $output); + } + + if (isset($this->command)) { + $this->getInput()->bind($this->command->getDefinition()); + } + + return parent::getRunner($application); + } + + protected function getArgument(\ReflectionParameter $parameter, ?string $type): mixed + { + return match ($type) { + Request::class => $this->request ??= Request::createFromGlobals(), + InputInterface::class => $this->getInput(), + OutputInterface::class => $this->output ??= new ConsoleOutput(), + Application::class => $this->console ??= new Application(), + Command::class => $this->command ??= new Command(), + default => parent::getArgument($parameter, $type), + }; + } + + protected static function register(GenericRuntime $runtime): GenericRuntime + { + $self = new self($runtime->options + ['runtimes' => []]); + $self->options['runtimes'] += [ + HttpKernelInterface::class => $self, + Request::class => $self, + Response::class => $self, + Application::class => $self, + Command::class => $self, + InputInterface::class => $self, + OutputInterface::class => $self, + ]; + $runtime->options = $self->options; + + return $self; + } + + private function getInput(): ArgvInput + { + if (!empty($_GET) && filter_var(\ini_get('register_argc_argv'), \FILTER_VALIDATE_BOOL)) { + throw new \Exception('CLI applications cannot be run safely on non-CLI SAPIs with register_argc_argv=On.'); + } + + if (isset($this->input)) { + return $this->input; + } + + $input = new ArgvInput(); + + if (isset($this->options['env'])) { + return $this->input = $input; + } + + if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) { + putenv($this->options['env_var_name'].'='.$_SERVER[$this->options['env_var_name']] = $_ENV[$this->options['env_var_name']] = $env); + } + + if ($input->hasParameterOption('--no-debug', true)) { + putenv($this->options['debug_var_name'].'='.$_SERVER[$this->options['debug_var_name']] = $_ENV[$this->options['debug_var_name']] = '0'); + } + + return $this->input = $input; + } +} diff --git a/lib/symfony/runtime/composer.json b/lib/symfony/runtime/composer.json new file mode 100644 index 000000000..4241bae48 --- /dev/null +++ b/lib/symfony/runtime/composer.json @@ -0,0 +1,45 @@ +{ + "name": "symfony/runtime", + "type": "composer-plugin", + "description": "Enables decoupling PHP applications from global state", + "keywords": ["runtime"], + "homepage": "https://symfony.com", + "license" : "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=8.1", + "composer-plugin-api": "^1.0|^2.0" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "symfony/console": "^5.4.9|^6.0.9|^7.0", + "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/dotenv": "<5.4" + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Runtime\\": "", + "Symfony\\Runtime\\Symfony\\Component\\": "Internal/" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "class": "Symfony\\Component\\Runtime\\Internal\\ComposerPlugin" + } +} diff --git a/lib/symfony/security-core/Resources/translations/security.af.xlf b/lib/symfony/security-core/Resources/translations/security.af.xlf index 7bcb92066..2592b8e98 100644 --- a/lib/symfony/security-core/Resources/translations/security.af.xlf +++ b/lib/symfony/security-core/Resources/translations/security.af.xlf @@ -72,11 +72,11 @@ Too many failed login attempts, please try again in %minutes% minute. - Te veel mislukte aanmeldpogings, probeer asseblief weer oor %minutes% minuut. + Te veel mislukte aanmeldpogings, probeer asseblief weer oor %minutes% minute. Too many failed login attempts, please try again in %minutes% minutes. - Te veel mislukte aanmeldpogings, probeer asseblief weer oor %minutes% minute. + Te veel mislukte aanmeldpogings, probeer asseblief weer oor %minutes% minute. diff --git a/lib/symfony/security-core/Resources/translations/security.az.xlf b/lib/symfony/security-core/Resources/translations/security.az.xlf index 25cb8605d..2981ce9cd 100644 --- a/lib/symfony/security-core/Resources/translations/security.az.xlf +++ b/lib/symfony/security-core/Resources/translations/security.az.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Çox sayda uğursuz giriş cəhdi, zəhmət olmasa %minutes% dəqiqə sonra yenidən cəhd edin.|Çox sayda uğursuz giriş cəhdi, zəhmət olmasa %minutes% dəqiqə sonra yenidən cəhd edin. + Çox sayda uğursuz giriş cəhdi, zəhmət olmasa %minutes% dəqiqə sonra yenidən cəhd edin.|Çox sayda uğursuz giriş cəhdi, zəhmət olmasa %minutes% dəqiqə sonra yenidən cəhd edin. diff --git a/lib/symfony/security-core/Resources/translations/security.et.xlf b/lib/symfony/security-core/Resources/translations/security.et.xlf index b87cb71ce..a35b03252 100644 --- a/lib/symfony/security-core/Resources/translations/security.et.xlf +++ b/lib/symfony/security-core/Resources/translations/security.et.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Liiga palju nurjunud sisselogimiskatseid, proovige uuesti %minutes% minuti pärast. + Liiga palju nurjunud sisselogimiskatseid, proovige uuesti %minutes% minuti pärast. diff --git a/lib/symfony/security-core/Resources/translations/security.hy.xlf b/lib/symfony/security-core/Resources/translations/security.hy.xlf index e506c9198..4a55569f5 100644 --- a/lib/symfony/security-core/Resources/translations/security.hy.xlf +++ b/lib/symfony/security-core/Resources/translations/security.hy.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Չափազանց շատ անհաջող մուտքի փորձեր, խնդրում ենք փորձել կրկին %minutes% րոպեից. + Չափազանց շատ անհաջող մուտքի փորձեր, խնդրում ենք փորձել կրկին %minutes% րոպեից. diff --git a/lib/symfony/security-core/Resources/translations/security.lt.xlf b/lib/symfony/security-core/Resources/translations/security.lt.xlf index 8053d0da2..fc285addf 100644 --- a/lib/symfony/security-core/Resources/translations/security.lt.xlf +++ b/lib/symfony/security-core/Resources/translations/security.lt.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Per daug nesėkmingų prisijungimo bandymų, bandykite vėl po %minutes% minutės.|Per daug nesėkmingų prisijungimo bandymų, bandykite vėl po %minutes% minučių. + Per daug nesėkmingų prisijungimo bandymų, bandykite vėl po %minutes% minutės.|Per daug nesėkmingų prisijungimo bandymų, bandykite vėl po %minutes% minučių. diff --git a/lib/symfony/security-core/Resources/translations/security.uz.xlf b/lib/symfony/security-core/Resources/translations/security.uz.xlf index ec690c5f4..a8c30d607 100644 --- a/lib/symfony/security-core/Resources/translations/security.uz.xlf +++ b/lib/symfony/security-core/Resources/translations/security.uz.xlf @@ -76,7 +76,7 @@ Too many failed login attempts, please try again in %minutes% minutes. - Koʻplab muvaffaqiyatsiz kirish urinishlari, iltimos, %minutes% daqiqadan so'ng qayta urinib koʻring.|Koʻplab muvaffaqiyatsiz kirish urinishlari, iltimos, %minutes% daqiqadan so'ng qayta urinib koʻring. + Koʻplab muvaffaqiyatsiz kirish urinishlari, iltimos, %minutes% daqiqadan so'ng qayta urinib koʻring.|Koʻplab muvaffaqiyatsiz kirish urinishlari, iltimos, %minutes% daqiqadan so'ng qayta urinib koʻring. diff --git a/lib/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php b/lib/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php index e72335a5e..4bbd70a07 100644 --- a/lib/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php +++ b/lib/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php @@ -47,9 +47,10 @@ final class WrappedTemplatedEmail { $file = $this->twig->getLoader()->getSourceContext($image); $body = $file->getPath() ? new File($file->getPath()) : $file->getCode(); - $this->message->addPart((new DataPart($body, $image, $contentType))->asInline()); + $dataPart = (new DataPart($body, $image, $contentType))->asInline(); + $this->message->addPart($dataPart); - return 'cid:'.$image; + return 'cid:'.$dataPart->getContentId(); } /** diff --git a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig index 990b324cb..0a43eedcd 100644 --- a/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig +++ b/lib/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig @@ -9,8 +9,9 @@ {%- if expanded is not defined or not expanded -%} {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} {%- endif -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%} - {{- parent() -}} +
+ {{- parent() -}} +
{%- endif -%} {%- endblock form_label %} diff --git a/lib/symfony/validator/Constraints/RegexValidator.php b/lib/symfony/validator/Constraints/RegexValidator.php index 4e9ae9039..5303e095b 100644 --- a/lib/symfony/validator/Constraints/RegexValidator.php +++ b/lib/symfony/validator/Constraints/RegexValidator.php @@ -47,7 +47,9 @@ class RegexValidator extends ConstraintValidator $value = ($constraint->normalizer)($value); } - if ($constraint->match xor preg_match($constraint->pattern, $value)) { + $expectedResult = $constraint->match ? 1 : 0; + + if (preg_match($constraint->pattern, $value) !== $expectedResult) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setParameter('{{ pattern }}', $constraint->pattern) diff --git a/lib/symfony/validator/Resources/translations/validators.az.xlf b/lib/symfony/validator/Resources/translations/validators.az.xlf index a9d281384..2d7237288 100644 --- a/lib/symfony/validator/Resources/translations/validators.az.xlf +++ b/lib/symfony/validator/Resources/translations/validators.az.xlf @@ -136,7 +136,7 @@ This value is not a valid IP address. - Bu dəyər etibarlı bir IP ünvanı deyil. + Bu dəyər etibarlı bir IP ünvanı deyil. This value is not a valid language. @@ -192,7 +192,7 @@ No temporary folder was configured in php.ini, or the configured folder does not exist. - php.ini-də müvəqqəti qovluq quraşdırılmayıb, və ya quraşdırılmış qovluq mövcud deyil. + php.ini-də müvəqqəti qovluq quraşdırılmayıb, və ya quraşdırılmış qovluq mövcud deyil. Cannot write temporary file to disk. @@ -224,7 +224,7 @@ This value is not a valid International Bank Account Number (IBAN). - Bu dəyər etibarlı bir Beynəlxalq Bank Hesab Nömrəsi (IBAN) deyil. + Bu dəyər etibarlı bir Beynəlxalq Bank Hesab Nömrəsi (IBAN) deyil. This value is not a valid ISBN-10. @@ -312,7 +312,7 @@ This value is not a valid Business Identifier Code (BIC). - Bu dəyər etibarlı bir Biznes Təyinat Kodu (BIC) deyil. + Bu dəyər etibarlı bir Biznes Təyinat Kodu (BIC) deyil. Error @@ -320,7 +320,7 @@ This value is not a valid UUID. - Bu dəyər etibarlı bir UUID deyil. + Bu dəyər etibarlı bir UUID deyil. This value should be a multiple of {{ compared_value }}. @@ -436,123 +436,123 @@ This value is not a valid MAC address. - Bu dəyər etibarlı bir MAC ünvanı deyil. + Bu dəyər etibarlı bir MAC ünvanı deyil. This URL is missing a top-level domain. - Bu URL yuxarı səviyyəli domeni çatışmır. + Bu URL yuxarı səviyyəli domeni çatışmır. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Bu dəyər çox qısadır. Heç olmasa bir söz daxil etməlisiniz.|Bu dəyər çox qısadır. Heç olmasa {{ min }} söz daxil etməlisiniz. + Bu dəyər çox qısadır. Heç olmasa bir söz daxil etməlisiniz.|Bu dəyər çox qısadır. Heç olmasa {{ min }} söz daxil etməlisiniz. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Bu dəyər çox uzundur. Yalnız bir söz daxil etməlisiniz.|Bu dəyər çox uzundur. {{ max }} və ya daha az söz daxil etməlisiniz. + Bu dəyər çox uzundur. Yalnız bir söz daxil etməlisiniz.|Bu dəyər çox uzundur. {{ max }} və ya daha az söz daxil etməlisiniz. This value does not represent a valid week in the ISO 8601 format. - Bu dəyər ISO 8601 formatında etibarlı bir həftəni təmsil etmir. + Bu dəyər ISO 8601 formatında etibarlı bir həftəni təmsil etmir. This value is not a valid week. - Bu dəyər etibarlı bir həftə deyil. + Bu dəyər etibarlı bir həftə deyil. This value should not be before week "{{ min }}". - Bu dəyər "{{ min }}" həftəsindən əvvəl olmamalıdır. + Bu dəyər "{{ min }}" həftəsindən əvvəl olmamalıdır. This value should not be after week "{{ max }}". - Bu dəyər "{{ max }}" həftəsindən sonra olmamalıdır. + Bu dəyər "{{ max }}" həftəsindən sonra olmamalıdır. This value is not a valid Twig template. - Bu dəyər etibarlı Twig şablonu deyil. + Bu dəyər etibarlı Twig şablonu deyil. This file is not a valid video. - Bu fayl etibarlı video deyil. + Bu fayl etibarlı video deyil. The size of the video could not be detected. - Videonun ölçüsünü təyin etmək mümkün olmadı. + Videonun ölçüsünü təyin etmək mümkün olmadı. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Video enliyi çox böyükdür ({{ width }}px). İcazə verilən maksimal enlik {{ max_width }}px-dir. + Video enliyi çox böyükdür ({{ width }}px). İcazə verilən maksimal enlik {{ max_width }}px-dir. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Video eni çox kiçikdir ({{ width }}px). Gözlənilən minimum en {{ min_width }}px-dir. + Video eni çox kiçikdir ({{ width }}px). Gözlənilən minimum en {{ min_width }}px-dir. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Video hündürlüyü çox böyükdür ({{ height }}px). İcazə verilən maksimum hündürlük {{ max_height }}px-dir. + Video hündürlüyü çox böyükdür ({{ height }}px). İcazə verilən maksimum hündürlük {{ max_height }}px-dir. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Videonun hündürlüyü çox kiçikdir ({{ height }}px). Gözlənilən minimum hündürlük {{ min_height }}px-dir. + Videonun hündürlüyü çox kiçikdir ({{ height }}px). Gözlənilən minimum hündürlük {{ min_height }}px-dir. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Videoda piksellərin sayı çox azdır ({{ pixels }}). Gözlənilən minimum miqdar {{ min_pixels }}-dir. + Videoda piksellərin sayı çox azdır ({{ pixels }}). Gözlənilən minimum miqdar {{ min_pixels }}-dir. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Videoda həddindən artıq piksel var ({{ pixels }}). Gözlənilən maksimum miqdar {{ max_pixels }}-dir. + Videoda həddindən artıq piksel var ({{ pixels }}). Gözlənilən maksimum miqdar {{ max_pixels }}-dir. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Video nisbəti çox böyükdür ({{ ratio }}). İcazə verilən maksimal nisbət {{ max_ratio }}‑dir. + Video nisbəti çox böyükdür ({{ ratio }}). İcazə verilən maksimal nisbət {{ max_ratio }}‑dir. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Video nisbəti çox kiçikdir ({{ ratio }}). Gözlənilən minimal nisbət {{ min_ratio }}. + Video nisbəti çox kiçikdir ({{ ratio }}). Gözlənilən minimal nisbət {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Video kvadratdır ({{ width }}x{{ height }}px). Kvadrat videolara icazə verilmir. + Video kvadratdır ({{ width }}x{{ height }}px). Kvadrat videolara icazə verilmir. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Video üfiqi istiqamətdədir ({{ width }}x{{ height }} piksel). Üfiqi videolara icazə verilmir. + Video üfiqi istiqamətdədir ({{ width }}x{{ height }} piksel). Üfiqi videolara icazə verilmir. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Video portret istiqamətindədir ({{ width }}x{{ height }} piksel). Portret istiqamətli videolara icazə verilmir. + Video portret istiqamətindədir ({{ width }}x{{ height }} piksel). Portret istiqamətli videolara icazə verilmir. The video file is corrupted. - Video faylı zədələnib. + Video faylı zədələnib. The video contains multiple streams. Only one stream is allowed. - Video bir neçə axın ehtiva edir. Yalnız bir axına icazə verilir. + Video bir neçə axın ehtiva edir. Yalnız bir axına icazə verilir. Unsupported video codec "{{ codec }}". - Dəstəklənməyən video kodeki "{{ codec }}". + Dəstəklənməyən video kodeki "{{ codec }}". Unsupported video container "{{ container }}". - Dəstəklənməyən video konteyneri "{{ container }}". + Dəstəklənməyən video konteyneri "{{ container }}". The image file is corrupted. - Şəkil faylı korlanıb. + Şəkil faylı korlanıb. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Şəkildə piksel sayı çox azdır ({{ pixels }}). Gözlənilən minimum miqdar {{ min_pixels }}. + Şəkildə piksel sayı çox azdır ({{ pixels }}). Gözlənilən minimum miqdar {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Şəkildə çox piksel var ({{ pixels }}). Gözlənilən maksimum say {{ max_pixels }}. + Şəkildə çox piksel var ({{ pixels }}). Gözlənilən maksimum say {{ max_pixels }}. This filename does not match the expected charset. - Bu fayl adı gözlənilən simvol dəstinə uyğun gəlmir. + Bu fayl adı gözlənilən simvol dəstinə uyğun gəlmir. diff --git a/lib/symfony/validator/Resources/translations/validators.bg.xlf b/lib/symfony/validator/Resources/translations/validators.bg.xlf index 79c06e5bc..4a58ab381 100644 --- a/lib/symfony/validator/Resources/translations/validators.bg.xlf +++ b/lib/symfony/validator/Resources/translations/validators.bg.xlf @@ -444,115 +444,115 @@ This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Тази стойност е твърде кратка. Трябва да съдържа поне една дума.|Тази стойност е твърде кратка. Трябва да съдържа поне {{ min }} думи. + Стойността е твърде кратка. Трябва да съдържа поне една дума.|Стойността е твърде кратка. Трябва да съдържа поне {{ min }} думи. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Тази стойност е твърде дълга. Трябва да съдържа само една дума.|Тази стойност е твърде дълга. Трябва да съдържа {{ max }} думи или по-малко. + Стойността е твърде дълга. Трябва да съдържа само една дума.|Стойността е твърде дълга. Трябва да съдържа {{ max }} думи или по-малко. This value does not represent a valid week in the ISO 8601 format. - Тази стойност не представлява валидна седмица във формат ISO 8601. + Тази стойност не представлява валидна седмица във формат ISO 8601. This value is not a valid week. - Тази стойност не е валидна седмица. + Тази стойност не е валидна седмица. This value should not be before week "{{ min }}". - Тази стойност не трябва да бъде преди седмица "{{ min }}". + Стойността не трябва да бъде преди седмица "{{ min }}". This value should not be after week "{{ max }}". - Тази стойност не трябва да бъде след седмица "{{ max }}". + Тази стойност не трябва да бъде след седмица "{{ max }}". This value is not a valid Twig template. - Тази стойност не е валиден Twig шаблон. + Тази стойност не е валиден Twig шаблон. This file is not a valid video. - Този файл не е валидно видео. + Този файл не е валидно видео. The size of the video could not be detected. - Размерът на видеото не може да бъде установен. + Размерът на видеото не може да бъде установен. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Ширината на видеото е твърде голяма ({{ width }}px). Допустимата максимална ширина е {{ max_width }}px. + Ширината на видеото е твърде голяма ({{ width }}px). Допустимата максимална ширина е {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Ширината на видеото е твърде малка ({{ width }}px). Минималната изисквана ширина е {{ min_width }}px. + Ширината на видеото е твърде малка ({{ width }}px). Минималната изисквана ширина е {{ min_width }}px. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Височината на видеото е твърде голяма ({{ height }}px). Максимално допустимата височина е {{ max_height }}px. + Височината на видеото е твърде голяма ({{ height }}px). Максимално допустимата височина е {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Височината на видеото е твърде малка ({{ height }}px). Очакваната минимална височина е {{ min_height }}px. + Височината на видеото е твърде малка ({{ height }}px). Очакваната минимална височина е {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Видеото има твърде малко пиксели ({{ pixels }}). Минимално изискуемото количество е {{ min_pixels }}. + Видеото има твърде малко пиксели ({{ pixels }}). Минимално изискуемото количество е {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Видеото има твърде много пиксели ({{ pixels }}). Очакваният максимум е {{ max_pixels }}. + Видеото има твърде много пиксели ({{ pixels }}). Максималният допустим брой е {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Съотношението на видеото е твърде голямо ({{ ratio }}). Позволеното максимално съотношение е {{ max_ratio }}. + Съотношението на видеото е твърде голямо ({{ ratio }}). Позволеното максимално съотношение е {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Съотношението на видеото е твърде малко ({{ ratio }}). Минималното очаквано съотношение е {{ min_ratio }}. + Съотношението на видеото е твърде малко ({{ ratio }}). Минималното очаквано съотношение е {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Видеото е квадратно ({{ width }}x{{ height }}px). Квадратни видеа не са позволени. + Видеото е квадратно ({{ width }}x{{ height }}px). Квадратни видеа не са позволени. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Видеото е в хоризонтална ориентация ({{ width }}x{{ height }} px). Хоризонтални видеа не са позволени. + Видеото е в хоризонтална ориентация ({{ width }}x{{ height }}px). Хоризонтални видеа не са позволени. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Видеото е с портретна ориентация ({{ width }}x{{ height }}px). Видеа с портретна ориентация не са позволени. + Видеото е с портретна ориентация ({{ width }}x{{ height }}px). Видеа с портретна ориентация не са позволени. The video file is corrupted. - Видеофайлът е повреден. + Видеофайлът е повреден. The video contains multiple streams. Only one stream is allowed. - Видеото съдържа множество потоци. Разрешен е само един поток. + Видеото съдържа множество потоци. Разрешен е само един поток. Unsupported video codec "{{ codec }}". - Неподдържан видео кодек „{{ codec }}“. + Неподдържан видео кодек „{{ codec }}“. Unsupported video container "{{ container }}". - Неподдържан видео контейнер "{{ container }}". + Неподдържан видео контейнер "{{ container }}". The image file is corrupted. - Файлът с изображение е повреден. + Файлът с изображение е повреден. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Изображението има твърде малко пиксели ({{ pixels }}). Очакваният минимален брой е {{ min_pixels }}. + Изображението има твърде малко пиксели ({{ pixels }}). Минималният изискуем брой е {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Изображението има твърде много пиксели ({{ pixels }}). Очакваният максимален брой е {{ max_pixels }}. + Изображението има твърде много пиксели ({{ pixels }}). Максималният допустим брой е {{ max_pixels }}. This filename does not match the expected charset. - Името на файла не съответства на очаквания набор от знаци. + Името на файла не съответства на очаквания набор от знаци. diff --git a/lib/symfony/validator/Resources/translations/validators.et.xlf b/lib/symfony/validator/Resources/translations/validators.et.xlf index 12a2671d9..cd53b1f20 100644 --- a/lib/symfony/validator/Resources/translations/validators.et.xlf +++ b/lib/symfony/validator/Resources/translations/validators.et.xlf @@ -440,119 +440,119 @@ This URL is missing a top-level domain. - Sellel URL-il puudub ülataseme domeen. + Sellel URL-il puudub ülataseme domeen. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - See väärtus on liiga lühike. See peaks sisaldama vähemalt ühte sõna.|See väärtus on liiga lühike. See peaks sisaldama vähemalt {{ min }} sõna. + See väärtus on liiga lühike. See peaks sisaldama vähemalt ühte sõna.|See väärtus on liiga lühike. See peaks sisaldama vähemalt {{ min }} sõna. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - See väärtus on liiga pikk. See peaks sisaldama ainult ühte sõna.|See väärtus on liiga pikk. See peaks sisaldama {{ max }} sõna või vähem. + See väärtus on liiga pikk. See peaks sisaldama ainult ühte sõna.|See väärtus on liiga pikk. See peaks sisaldama {{ max }} sõna või vähem. This value does not represent a valid week in the ISO 8601 format. - See väärtus ei esinda kehtivat nädalat ISO 8601 formaadis. + See väärtus ei esinda kehtivat nädalat ISO 8601 formaadis. This value is not a valid week. - See väärtus ei ole kehtiv nädal. + See väärtus ei ole kehtiv nädal. This value should not be before week "{{ min }}". - See väärtus ei tohiks olla enne nädalat "{{ min }}". + See väärtus ei tohiks olla enne nädalat "{{ min }}". This value should not be after week "{{ max }}". - See väärtus ei tohiks olla pärast nädalat "{{ max }}". + See väärtus ei tohiks olla pärast nädalat "{{ max }}". This value is not a valid Twig template. - See väärtus ei ole kehtiv Twig'i mall. + See väärtus ei ole kehtiv Twig'i mall. This file is not a valid video. - See fail ei ole kehtiv video. + See fail ei ole kehtiv video. The size of the video could not be detected. - Video suurust ei õnnestunud tuvastada. + Video suurust ei õnnestunud tuvastada. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Video laius on liiga suur ({{ width }}px). Lubatud maksimaalne laius on {{ max_width }}px. + Video laius on liiga suur ({{ width }}px). Lubatud maksimaalne laius on {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Video laius on liiga väike ({{ width }}px). Oodatav minimaalne laius on {{ min_width }} px. + Video laius on liiga väike ({{ width }}px). Oodatav minimaalne laius on {{ min_width }} px. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Video kõrgus on liiga suur ({{ height }}px). Lubatud maksimaalne kõrgus on {{ max_height }}px. + Video kõrgus on liiga suur ({{ height }}px). Lubatud maksimaalne kõrgus on {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Video kõrgus on liiga väike ({{ height }}px). Oodatav minimaalne kõrgus on {{ min_height }}px. + Video kõrgus on liiga väike ({{ height }}px). Oodatav minimaalne kõrgus on {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Videol on liiga vähe piksleid ({{ pixels }}). Oodatav miinimum on {{ min_pixels }}. + Videol on liiga vähe piksleid ({{ pixels }}). Oodatav miinimum on {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Videol on liiga palju piksleid ({{ pixels }}). Eeldatav maksimaalne kogus on {{ max_pixels }}. + Videol on liiga palju piksleid ({{ pixels }}). Eeldatav maksimaalne kogus on {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Video suhe on liiga suur ({{ ratio }}). Lubatud maksimaalne suhe on {{ max_ratio }}. + Video suhe on liiga suur ({{ ratio }}). Lubatud maksimaalne suhe on {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Video kuvasuhe on liiga väike ({{ ratio }}). Eeldatav miinimumsuhe on {{ min_ratio }}. + Video kuvasuhe on liiga väike ({{ ratio }}). Eeldatav miinimumsuhe on {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Video on ruudukujuline ({{ width }}x{{ height }}px). Ruutvideod pole lubatud. + Video on ruudukujuline ({{ width }}x{{ height }}px). Ruutvideod pole lubatud. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Video on horisontaalses asendis ({{ width }}x{{ height }} px). Horisontaalseid videoid ei ole lubatud. + Video on horisontaalses asendis ({{ width }}x{{ height }} px). Horisontaalseid videoid ei ole lubatud. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Video on püstsuunas ({{ width }}x{{ height }} px). Püstsuunalised videod pole lubatud. + Video on püstsuunas ({{ width }}x{{ height }} px). Püstsuunalised videod pole lubatud. The video file is corrupted. - Videofail on rikutud. + Videofail on rikutud. The video contains multiple streams. Only one stream is allowed. - Video sisaldab mitu voogu. Lubatud on ainult üks voog. + Video sisaldab mitu voogu. Lubatud on ainult üks voog. Unsupported video codec "{{ codec }}". - Toetamata videokoodek „{{ codec }}“. + Toetamata videokoodek „{{ codec }}“. Unsupported video container "{{ container }}". - Toetamata videokonteiner "{{ container }}". + Toetamata videokonteiner "{{ container }}". The image file is corrupted. - Pildifail on rikutud. + Pildifail on rikutud. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Pildil on liiga vähe piksleid ({{ pixels }}). Oodatav miinimum on {{ min_pixels }}. + Pildil on liiga vähe piksleid ({{ pixels }}). Oodatav miinimum on {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Pildil on liiga palju piksleid ({{ pixels }}). Oodatav maksimaalne hulk on {{ max_pixels }}. + Pildil on liiga palju piksleid ({{ pixels }}). Oodatav maksimaalne hulk on {{ max_pixels }}. This filename does not match the expected charset. - See failinimi ei vasta eeldatavale märgistikule. + See failinimi ei vasta eeldatavale märgistikule. diff --git a/lib/symfony/validator/Resources/translations/validators.he.xlf b/lib/symfony/validator/Resources/translations/validators.he.xlf index e19c438e4..d184a11a5 100644 --- a/lib/symfony/validator/Resources/translations/validators.he.xlf +++ b/lib/symfony/validator/Resources/translations/validators.he.xlf @@ -440,119 +440,119 @@ This URL is missing a top-level domain. - לכתובת URL זו חסר דומיין רמה עליונה. + לכתובת URL זו חסר דומיין רמה עליונה. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - ערך זה קצר מדי. הוא צריך להכיל לפחות מילה אחת.|ערך זה קצר מדי. הוא צריך להכיל לפחות {{ min }} מילים. + ערך זה קצר מדי. הוא צריך להכיל לפחות מילה אחת.|ערך זה קצר מדי. הוא צריך להכיל לפחות {{ min }} מילים. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - ערך זה ארוך מדי. הוא צריך להכיל רק מילה אחת.|ערך זה ארוך מדי. הוא צריך להכיל {{ max }} מילים או פחות. + ערך זה ארוך מדי. הוא צריך להכיל רק מילה אחת.|ערך זה ארוך מדי. הוא צריך להכיל {{ max }} מילים או פחות. This value does not represent a valid week in the ISO 8601 format. - ערך זה אינו מייצג שבוע תקף בפורמט ISO 8601. + ערך זה אינו מייצג שבוע תקף בפורמט ISO 8601. This value is not a valid week. - ערך זה אינו שבוע חוקי. + ערך זה אינו שבוע חוקי. This value should not be before week "{{ min }}". - ערך זה לא אמור להיות לפני שבוע "{{ min }}". + ערך זה לא אמור להיות לפני שבוע "{{ min }}". This value should not be after week "{{ max }}". - ערך זה לא אמור להיות לאחר שבוע "{{ max }}". + ערך זה לא אמור להיות לאחר שבוע "{{ max }}". This value is not a valid Twig template. - ערך זה אינו תבנית Twig חוקית. + ערך זה אינו תבנית Twig חוקית. This file is not a valid video. - קובץ זה אינו וידאו תקין. + קובץ זה אינו וידאו תקין. The size of the video could not be detected. - לא ניתן היה לזהות את גודל הווידאו. + לא ניתן היה לזהות את גודל הווידאו. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - רוחב הווידאו גדול מדי ({{ width }}px). רוחב מרבי מותר הוא {{ max_width }}px. + רוחב הווידאו גדול מדי ({{ width }}px). רוחב מרבי מותר הוא {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - רוחב הווידאו קטן מדי ({{ width }}px). רוחב מינימלי צפוי הוא {{ min_width }} פיקסלים. + רוחב הווידאו קטן מדי ({{ width }}px). רוחב מינימלי צפוי הוא {{ min_width }} פיקסלים. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - גובה הווידאו גדול מדי ({{ height }}px). הגובה המקסימלי המותר הוא {{ max_height }}px. + גובה הווידאו גדול מדי ({{ height }}px). הגובה המקסימלי המותר הוא {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - גובה הווידאו קטן מדי ({{ height }}px). הגובה המינימלי הצפוי הוא {{ min_height }}px. + גובה הווידאו קטן מדי ({{ height }}px). הגובה המינימלי הצפוי הוא {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - לסרטון יש מעט מדי פיקסלים ({{ pixels }}). הכמות המינימלית הצפויה היא {{ min_pixels }}. + לסרטון יש מעט מדי פיקסלים ({{ pixels }}). הכמות המינימלית הצפויה היא {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - לסרטון יש יותר מדי פיקסלים ({{ pixels }}). הכמות המרבית הצפויה היא {{ max_pixels }}. + לסרטון יש יותר מדי פיקסלים ({{ pixels }}). הכמות המרבית הצפויה היא {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - יחס הווידאו גדול מדי ({{ ratio }}). יחס מקסימלי מותר הוא {{ max_ratio }}. + יחס הווידאו גדול מדי ({{ ratio }}). יחס מקסימלי מותר הוא {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - יחס הווידאו קטן מדי ({{ ratio }}). יחס מינימלי צפוי הוא {{ min_ratio }}. + יחס הווידאו קטן מדי ({{ ratio }}). יחס מינימלי צפוי הוא {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - הווידאו הוא מרובע ({{ width }}x{{ height }}px). סרטוני וידאו מרובעים אינם מותרים. + הווידאו הוא מרובע ({{ width }}x{{ height }}px). סרטוני וידאו מרובעים אינם מותרים. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - הווידאו במצב לרוחב ({{ width }}x{{ height }} פיקסלים). סרטוני לרוחב אינם מותרים. + הווידאו במצב לרוחב ({{ width }}x{{ height }} פיקסלים). סרטוני לרוחב אינם מותרים. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - הווידאו הוא בתצורת דיוקן ({{ width }}x{{ height }}px). סרטוני וידאו בתצורת דיוקן אינם מותרים. + הווידאו הוא בתצורת דיוקן ({{ width }}x{{ height }}px). סרטוני וידאו בתצורת דיוקן אינם מותרים. The video file is corrupted. - קובץ הווידאו פגום. + קובץ הווידאו פגום. The video contains multiple streams. Only one stream is allowed. - הווידאו מכיל מספר זרמים. מותר זרם אחד בלבד. + הווידאו מכיל מספר זרמים. מותר זרם אחד בלבד. Unsupported video codec "{{ codec }}". - מקודד וידאו שאינו נתמך "{{ codec }}". + מקודד וידאו שאינו נתמך "{{ codec }}". Unsupported video container "{{ container }}". - מיכל וידאו שאינו נתמך "{{ container }}". + מיכל וידאו שאינו נתמך "{{ container }}". The image file is corrupted. - קובץ התמונה פגום. + קובץ התמונה פגום. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - לתמונה יש מעט מדי פיקסלים ({{ pixels }}). הכמות המינימלית הצפויה היא {{ min_pixels }}. + לתמונה יש מעט מדי פיקסלים ({{ pixels }}). הכמות המינימלית הצפויה היא {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - לתמונה יש יותר מדי פיקסלים ({{ pixels }}). הכמות המרבית הצפויה היא {{ max_pixels }}. + לתמונה יש יותר מדי פיקסלים ({{ pixels }}). הכמות המרבית הצפויה היא {{ max_pixels }}. This filename does not match the expected charset. - שם הקובץ הזה אינו תואם את מערך התווים הצפוי. + שם הקובץ הזה אינו תואם את מערך התווים הצפוי. diff --git a/lib/symfony/validator/Resources/translations/validators.hy.xlf b/lib/symfony/validator/Resources/translations/validators.hy.xlf index e537733c7..bd59319d1 100644 --- a/lib/symfony/validator/Resources/translations/validators.hy.xlf +++ b/lib/symfony/validator/Resources/translations/validators.hy.xlf @@ -136,7 +136,7 @@ This value is not a valid IP address. - Այս արժեքը վավեր IP հասցե չէ։ + Այս արժեքը վավեր IP հասցե չէ։ This value is not a valid language. @@ -192,7 +192,7 @@ No temporary folder was configured in php.ini, or the configured folder does not exist. - php.ini-ում չի կարգավորվել ժամանակավոր թղթապանակ, կամ կարգավորված թղթապանակը չկա։ + php.ini-ում չի կարգավորվել ժամանակավոր թղթապանակ, կամ կարգավորված թղթապանակը չկա։ Cannot write temporary file to disk. @@ -224,7 +224,7 @@ This value is not a valid International Bank Account Number (IBAN). - Այս արժեքը վավեր միջազգային բանկային հաշվի համար (IBAN) չէ։ + Այս արժեքը վավեր միջազգային բանկային հաշվի համար (IBAN) չէ։ This value is not a valid ISBN-10. @@ -312,7 +312,7 @@ This value is not a valid Business Identifier Code (BIC). - Այս արժեքը վավեր բիզնեսի նորմատիվ կոդ (BIC) չէ։ + Այս արժեքը վավեր բիզնեսի նորմատիվ կոդ (BIC) չէ։ Error @@ -320,7 +320,7 @@ This value is not a valid UUID. - Այս արժեքը վավեր UUID չէ։ + Այս արժեքը վավեր UUID չէ։ This value should be a multiple of {{ compared_value }}. @@ -392,167 +392,167 @@ This value is not a valid CSS color. - Այս արժեքը վավեր CSS գույն չէ։ + Այս արժեքը վավեր CSS գույն չէ։ This value is not a valid CIDR notation. - Այս արժեքը վավեր CIDR նշում չէ։ + Այս արժեքը վավեր CIDR նշում չէ։ The value of the netmask should be between {{ min }} and {{ max }}. - Ցանցային դիմակի արժեքը պետք է լինի {{ min }}-ի և {{ max }}-ի միջև։ + Ցանցային դիմակի արժեքը պետք է լինի {{ min }}-ի և {{ max }}-ի միջև։ The filename is too long. It should have {{ filename_max_length }} character or less.|The filename is too long. It should have {{ filename_max_length }} characters or less. - Ֆայլի անունը շատ երկար է։ Այն պետք է ունենա {{ filename_max_length }} նիշ կամ պակաս։ + Ֆայլի անունը շատ երկար է։ Այն պետք է ունենա {{ filename_max_length }} նիշ կամ պակաս։ The password strength is too low. Please use a stronger password. - Գաղտնաբառի անվտանգությունը շատ ցածր է։ Խնդրում ենք գործածել ավելի ամրագույն գաղտնաբառ։ + Գաղտնաբառի անվտանգությունը շատ ցածր է։ Խնդրում ենք գործածել ավելի ամրագույն գաղտնաբառ։ This value contains characters that are not allowed by the current restriction-level. - Այս արժեքը պարունակում է այն նիշերը, որոնք չեն թույլատրվում ըստ ընթացիկ սահմանումների։ + Այս արժեքը պարունակում է այն նիշերը, որոնք չեն թույլատրվում ըստ ընթացիկ սահմանումների։ Using invisible characters is not allowed. - Անտեսանելի նիշերի օգտագործումը չի թույլատրվում։ + Անտեսանելի նիշերի օգտագործումը չի թույլատրվում։ Mixing numbers from different scripts is not allowed. - Թվերի խառնուրդը տարբեր սցենարներից չի թույլատրվում։ + Թվերի խառնուրդը տարբեր սցենարներից չի թույլատրվում։ Using hidden overlay characters is not allowed. - Թաքնված ծածկանիշերի օգտագործումը չի թույլատրվում։ + Թաքնված ծածկանիշերի օգտագործումը չի թույլատրվում։ The extension of the file is invalid ({{ extension }}). Allowed extensions are {{ extensions }}. - Ֆայլի ընդլայնումը անվավեր է ({{ extension }})։ Թույլատրվող ընդլայնումներն են՝ {{ extensions }}։ + Ֆայլի ընդլայնումը անվավեր է ({{ extension }})։ Թույլատրվող ընդլայնումներն են՝ {{ extensions }}։ The detected character encoding is invalid ({{ detected }}). Allowed encodings are {{ encodings }}. - Հայտնաբերված նիշագրության կոդը անվավեր է ({{ detected }})։ Թույլատրվող կոդերն են՝ {{ encodings }}։ + Հայտնաբերված նիշագրության կոդը անվավեր է ({{ detected }})։ Թույլատրվող կոդերն են՝ {{ encodings }}։ This value is not a valid MAC address. - Այս արժեքը վավեր MAC հասցե չէ։ + Այս արժեքը վավեր MAC հասցե չէ։ This URL is missing a top-level domain. - Այս URL-ը չունի վերին մակարդակի դոմեյն: + Այս URL-ը չունի վերին մակարդակի դոմեյն: This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Այս արժեքը շատ կարճ է: պետք է պարունակի գոնե մեկ բառ.|Այս արժեքը շատ կարճ է: պետք է պարունակի գոնե {{ min }} բառեր: + Այս արժեքը շատ կարճ է: պետք է պարունակի գոնե մեկ բառ.|Այս արժեքը շատ կարճ է: պետք է պարունակի գոնե {{ min }} բառեր: This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Այս արժեքը շատ երկար է: պետք է պարունակի միայն մեկ բառ.|Այս արժեքը շատ երկար է: պետք է պարունակի {{ max }} բառ կամ ավելի քիչ: + Այս արժեքը շատ երկար է: պետք է պարունակի միայն մեկ բառ.|Այս արժեքը շատ երկար է: պետք է պարունակի {{ max }} բառ կամ ավելի քիչ: This value does not represent a valid week in the ISO 8601 format. - Այս արժեքը չի ներկայացնում ISO 8601 ձևաչափով գործող շաբաթ։ + Այս արժեքը չի ներկայացնում ISO 8601 ձևաչափով գործող շաբաթ։ This value is not a valid week. - Այս արժեքը վավեր շաբաթ չէ: + Այս արժեքը վավեր շաբաթ չէ: This value should not be before week "{{ min }}". - Այս արժեքը չպետք է լինի «{{ min }}» շաբաթից առաջ։ + Այս արժեքը չպետք է լինի «{{ min }}» շաբաթից առաջ։ This value should not be after week "{{ max }}". - Այս արժեքը չպետք է լինի «{{ max }}» շաբաթից հետո։ + Այս արժեքը չպետք է լինի «{{ max }}» շաբաթից հետո։ This value is not a valid Twig template. - Այս արժեքը վավեր Twig ձևանմուշ չէ: + Այս արժեքը վավեր Twig ձևանմուշ չէ: This file is not a valid video. - Այս ֆայլը վավեր տեսանյութ չէ։ + Այս ֆայլը վավեր տեսանյութ չէ։ The size of the video could not be detected. - Չհաջողվեց հայտնաբերել տեսանյութի չափը. + Չհաջողվեց հայտնաբերել տեսանյութի չափը. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Տեսահոլովակի լայնությունը չափազանց մեծ է ({{ width }}px)։ Թույլատրելի առավելագույն լայնությունը {{ max_width }}px է։ + Տեսահոլովակի լայնությունը չափազանց մեծ է ({{ width }}px)։ Թույլատրելի առավելագույն լայնությունը {{ max_width }}px է։ The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Տեսանյութի լայնությունը չափազանց փոքր է ({{ width }}px). Սպասվող նվազագույն լայնքը {{ min_width }}px է. + Տեսանյութի լայնությունը չափազանց փոքր է ({{ width }}px). Սպասվող նվազագույն լայնքը {{ min_width }}px է. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Վիդեոյի բարձրությունը չափազանց մեծ է ({{ height }}px)։ Թույլատրելի առավելագույն բարձրությունը {{ max_height }}px է։ + Վիդեոյի բարձրությունը չափազանց մեծ է ({{ height }}px)։ Թույլատրելի առավելագույն բարձրությունը {{ max_height }}px է։ The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Վիդեոյի բարձրությունը շատ փոքր է ({{ height }}px)։ Սպասվող նվազագույն բարձրությունը {{ min_height }}px է։ + Վիդեոյի բարձրությունը շատ փոքր է ({{ height }}px)։ Սպասվող նվազագույն բարձրությունը {{ min_height }}px է։ The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Տեսանյութը ունի չափազանց քիչ պիքսելներ ({{ pixels }}). Սպասվող նվազագույն քանակը {{ min_pixels }} է։ + Տեսանյութը ունի չափազանց քիչ պիքսելներ ({{ pixels }}). Սպասվող նվազագույն քանակը {{ min_pixels }} է։ The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Տեսանյութը ունի չափազանց շատ պիքսելներ ({{ pixels }}). Սպասվող առավելագույն քանակը {{ max_pixels }} է։ + Տեսանյութը ունի չափազանց շատ պիքսելներ ({{ pixels }}). Սպասվող առավելագույն քանակը {{ max_pixels }} է։ The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Տեսանյութի հարաբերակցությունը չափազանց մեծ է ({{ ratio }}): Թույլատրելի առավելագույն հարաբերակցությունը {{ max_ratio }} է։ + Տեսանյութի հարաբերակցությունը չափազանց մեծ է ({{ ratio }}): Թույլատրելի առավելագույն հարաբերակցությունը {{ max_ratio }} է։ The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Վիդեոյի հարաբերակցությունը շատ փոքր է ({{ ratio }}). Ավելի փոքրագույն սպասվող հարաբերակցությունը {{ min_ratio }} է. + Վիդեոյի հարաբերակցությունը շատ փոքր է ({{ ratio }}). Ավելի փոքրագույն սպասվող հարաբերակցությունը {{ min_ratio }} է. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Տեսանյութը քառակուսի է ({{ width }}x{{ height }}px). Քառակուսի տեսանյութերը թույլատրելի չեն. + Տեսանյութը քառակուսի է ({{ width }}x{{ height }}px). Քառակուսի տեսանյութերը թույլատրելի չեն. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Տեսանյութը հորիզոնական կողմնորոշմամբ է ({{ width }}x{{ height }} px). Հորիզոնական տեսանյութերը թույլատրելի չեն. + Տեսանյութը հորիզոնական կողմնորոշմամբ է ({{ width }}x{{ height }} px). Հորիզոնական տեսանյութերը թույլատրելի չեն. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Վիդեոն ուղղահայաց կողմնորոշված է ({{ width }}x{{ height }}px)։ Ուղղահայաց կողմնորոշմամբ տեսանյութերը թույլատրելի չեն։ + Վիդեոն ուղղահայաց կողմնորոշված է ({{ width }}x{{ height }}px)։ Ուղղահայաց կողմնորոշմամբ տեսանյութերը թույլատրելի չեն։ The video file is corrupted. - Տեսանյութի ֆայլը վնասված է. + Տեսանյութի ֆայլը վնասված է. The video contains multiple streams. Only one stream is allowed. - Տեսանյութը պարունակում է բազմաթիվ հոսքեր։ Թույլատրվում է միայն մեկ հոսք։ + Տեսանյութը պարունակում է բազմաթիվ հոսքեր։ Թույլատրվում է միայն մեկ հոսք։ Unsupported video codec "{{ codec }}". - Չաջակցվող տեսանյութի կոդեկ «{{ codec }}»։ + Չաջակցվող տեսանյութի կոդեկ «{{ codec }}»։ Unsupported video container "{{ container }}". - Չաջակցվող վիդեո կոնտեյներ "{{ container }}". + Չաջակցվող վիդեո կոնտեյներ "{{ container }}". The image file is corrupted. - Պատկերի ֆայլը վնասված է։ + Պատկերի ֆայլը վնասված է։ The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Պատկերը ունի չափազանց քիչ պիքսելներ ({{ pixels }}). Սպասվող նվազագույնը {{ min_pixels }} է։ + Պատկերը ունի չափազանց քիչ պիքսելներ ({{ pixels }}). Սպասվող նվազագույնը {{ min_pixels }} է։ The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Պատկերը ունի չափազանց շատ պիքսել ({{ pixels }}). Սպասվող առավելագույն քանակը {{ max_pixels }} է. + Պատկերը ունի չափազանց շատ պիքսել ({{ pixels }}). Սպասվող առավելագույն քանակը {{ max_pixels }} է. This filename does not match the expected charset. - Այս ֆայլի անունը չի համապատասխանում սպասվող նիշքերի հավաքածուին. + Այս ֆայլի անունը չի համապատասխանում սպասվող նիշքերի հավաքածուին. diff --git a/lib/symfony/validator/Resources/translations/validators.lt.xlf b/lib/symfony/validator/Resources/translations/validators.lt.xlf index ab4bdc57e..0d03648c2 100644 --- a/lib/symfony/validator/Resources/translations/validators.lt.xlf +++ b/lib/symfony/validator/Resources/translations/validators.lt.xlf @@ -452,107 +452,107 @@ This value does not represent a valid week in the ISO 8601 format. - Ši reikšmė neatitinka galiojančios savaitės ISO 8601 formatu. + Ši reikšmė neatitinka galiojančios savaitės ISO 8601 formatu. This value is not a valid week. - Ši reikšmė nėra galiojanti savaitė. + Ši reikšmė nėra galiojanti savaitė. This value should not be before week "{{ min }}". - Ši reikšmė neturėtų būti prieš savaitę "{{ min }}". + Ši reikšmė neturėtų būti prieš savaitę "{{ min }}". This value should not be after week "{{ max }}". - Ši reikšmė neturėtų būti po savaitės "{{ max }}". + Ši reikšmė neturėtų būti po savaitės "{{ max }}". This value is not a valid Twig template. - Ši reikšmė nėra tinkamas „Twig“ šablonas. + Ši reikšmė nėra tinkamas „Twig“ šablonas. This file is not a valid video. - Šis failas nėra galiojantis vaizdo įrašas. + Šis failas nėra galiojantis vaizdo įrašas. The size of the video could not be detected. - Nepavyko nustatyti vaizdo įrašo dydžio. + Nepavyko nustatyti vaizdo įrašo dydžio. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Vaizdo įrašo plotis per didelis ({{ width }}px). Leidžiamas didžiausias plotis yra {{ max_width }}px. + Vaizdo įrašo plotis per didelis ({{ width }}px). Leidžiamas didžiausias plotis yra {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Vaizdo įrašo plotis per mažas ({{ width }}px). Tikėtinas mažiausias plotis yra {{ min_width }}px. + Vaizdo įrašo plotis per mažas ({{ width }}px). Tikėtinas mažiausias plotis yra {{ min_width }}px. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Vaizdo aukštis per didelis ({{ height }}px). Leidžiamas maksimalus aukštis yra {{ max_height }}px. + Vaizdo aukštis per didelis ({{ height }}px). Leidžiamas maksimalus aukštis yra {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Vaizdo aukštis per mažas ({{ height }}px). Tikėtinas minimalus aukštis yra {{ min_height }}px. + Vaizdo aukštis per mažas ({{ height }}px). Tikėtinas minimalus aukštis yra {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Vaizdo įraše per mažai pikselių ({{ pixels }}). Tikimasi mažiausiai {{ min_pixels }}. + Vaizdo įraše per mažai pikselių ({{ pixels }}). Tikimasi mažiausiai {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Vaizdo įraše per daug pikselių ({{ pixels }}). Tikimasi, kad didžiausias kiekis yra {{ max_pixels }}. + Vaizdo įraše per daug pikselių ({{ pixels }}). Tikimasi, kad didžiausias kiekis yra {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Vaizdo santykis per didelis ({{ ratio }}). Leidžiamas didžiausias santykis yra {{ max_ratio }}. + Vaizdo santykis per didelis ({{ ratio }}). Leidžiamas didžiausias santykis yra {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Vaizdo santykis per mažas ({{ ratio }}). Tikimasi mažiausias santykis yra {{ min_ratio }}. + Vaizdo santykis per mažas ({{ ratio }}). Tikimasi mažiausias santykis yra {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Vaizdo įrašas yra kvadratinis ({{ width }}x{{ height }}px). Kvadratiniai vaizdo įrašai neleidžiami. + Vaizdo įrašas yra kvadratinis ({{ width }}x{{ height }}px). Kvadratiniai vaizdo įrašai neleidžiami. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Vaizdo įrašas yra gulsčio formato ({{ width }}x{{ height }} px). Gulsčio formato vaizdo įrašai neleidžiami. + Vaizdo įrašas yra gulsčio formato ({{ width }}x{{ height }} px). Gulsčio formato vaizdo įrašai neleidžiami. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Vaizdo įrašas yra portreto orientacijos ({{ width }}x{{ height }}px). Portreto orientacijos vaizdo įrašai neleidžiami. + Vaizdo įrašas yra portreto orientacijos ({{ width }}x{{ height }}px). Portreto orientacijos vaizdo įrašai neleidžiami. The video file is corrupted. - Vaizdo failas sugadintas. + Vaizdo failas sugadintas. The video contains multiple streams. Only one stream is allowed. - Vaizdo įraše yra keli srautai. Leidžiamas tik vienas srautas. + Vaizdo įraše yra keli srautai. Leidžiamas tik vienas srautas. Unsupported video codec "{{ codec }}". - Nepalaikomas vaizdo kodekas „{{ codec }}“. + Nepalaikomas vaizdo kodekas „{{ codec }}“. Unsupported video container "{{ container }}". - Nepalaikomas vaizdo konteineris "{{ container }}". + Nepalaikomas vaizdo konteineris "{{ container }}". The image file is corrupted. - Paveikslėlio failas sugadintas. + Paveikslėlio failas sugadintas. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Paveikslėlyje per mažai pikselių ({{ pixels }}). Tikimasi mažiausiai {{ min_pixels }}. + Paveikslėlyje per mažai pikselių ({{ pixels }}). Tikimasi mažiausiai {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Paveikslėlis turi per daug pikselių ({{ pixels }}). Tikėtinas didžiausias kiekis yra {{ max_pixels }}. + Paveikslėlis turi per daug pikselių ({{ pixels }}). Tikėtinas didžiausias kiekis yra {{ max_pixels }}. This filename does not match the expected charset. - Šis failo pavadinimas neatitinka laukiamo ženklų rinkinio. + Šis failo pavadinimas neatitinka laukiamo ženklų rinkinio. diff --git a/lib/symfony/validator/Resources/translations/validators.sl.xlf b/lib/symfony/validator/Resources/translations/validators.sl.xlf index 515e5d0aa..14d1485c5 100644 --- a/lib/symfony/validator/Resources/translations/validators.sl.xlf +++ b/lib/symfony/validator/Resources/translations/validators.sl.xlf @@ -468,91 +468,91 @@ This value is not a valid Twig template. - Ta vrednost ni veljavna predloga Twig. + Ta vrednost ni veljavna predloga Twig. This file is not a valid video. - Ta datoteka ni veljaven video. + Ta datoteka ni veljavna videodatoteka. The size of the video could not be detected. - Velikosti videoposnetka ni bilo mogoče zaznati. + Velikosti videoposnetka ni bilo mogoče določiti. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Širina videoposnetka je prevelika ({{ width }}px). Dovoljena največja širina je {{ max_width }}px. + Širina videoposnetka je prevelika ({{ width }}px). Največja dovoljena širina je {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Širina videa je premajhna ({{ width }}px). Pričakovana minimalna širina je {{ min_width }} px. + Širina videoposnetka je premajhna ({{ width }}px). Najmanjša pričakovana širina je {{ min_width }}px. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Višina videa je prevelika ({{ height }}px). Dovoljena največja višina je {{ max_height }}px. + Višina videoposnetka je prevelika ({{ height }}px). Največja dovoljena višina je {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Višina videa je premajhna ({{ height }}px). Pričakovana najmanjša višina je {{ min_height }}px. + Višina videoposnetka je premajhna ({{ height }}px). Najmanjša pričakovana višina je {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Video ima premalo slikovnih pik ({{ pixels }}). Pričakovana minimalna količina je {{ min_pixels }}. + Videoposnetek ima premalo slikovnih pik ({{ pixels }}). Najmanjše pričakovano število je {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Video ima preveč slikovnih pik ({{ pixels }}). Pričakovano največje število je {{ max_pixels }}. + Videoposnetek ima preveč slikovnih pik ({{ pixels }}). Največje pričakovano število je {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Razmerje videa je preveliko ({{ ratio }}). Dovoljeno največje razmerje je {{ max_ratio }}. + Razmerje videoposnetka je preveliko ({{ ratio }}). Največje dovoljeno razmerje je {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Razmerje videa je premajhno ({{ ratio }}). Pričakovano minimalno razmerje je {{ min_ratio }}. + Razmerje videoposnetka je premajhno ({{ ratio }}). Najmanjše pričakovano razmerje je {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Video je kvadratno ({{ width }}x{{ height }}px). Kvadratni videoposnetki niso dovoljeni. + Videoposnetek je kvadraten ({{ width }}x{{ height }}px). Kvadratni videoposnetki niso dovoljeni. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Video je vodoravno orientiran ({{ width }}x{{ height }} px). Vodoravni videi niso dovoljeni. + Videoposnetek je ležeče usmerjen ({{ width }}x{{ height }}px). Ležeče usmerjeni videoposnetki niso dovoljeni. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Video je usmerjeno pokonci ({{ width }}x{{ height }}px). Videi v pokončni usmeritvi niso dovoljeni. + Videoposnetek je pokončno usmerjen ({{ width }}x{{ height }}px). Pokončno usmerjeni videoposnetki niso dovoljeni. The video file is corrupted. - Videodatoteka je poškodovana. + Videodatoteka je poškodovana. The video contains multiple streams. Only one stream is allowed. - Video vsebuje več tokov. Dovoljen je le en tok. + Videoposnetek vsebuje več tokov. Dovoljen je le en tok. Unsupported video codec "{{ codec }}". - Nepodprti video kodek »{{ codec }}«. + Nepodprt videokodek "{{ codec }}". Unsupported video container "{{ container }}". - Nepodprt videokontejner "{{ container }}". + Nepodprt videovsebnik "{{ container }}". The image file is corrupted. - Slikovna datoteka je poškodovana. + Slikovna datoteka je poškodovana. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Slika ima premalo slikovnih točk ({{ pixels }}). Pričakovana minimalna količina je {{ min_pixels }}. + Slika ima premalo slikovnih pik ({{ pixels }}). Najmanjše pričakovano število je {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Slika ima preveč slikovnih pik ({{ pixels }}). Pričakovano največje število je {{ max_pixels }}. + Slika ima preveč slikovnih pik ({{ pixels }}). Največje pričakovano število je {{ max_pixels }}. This filename does not match the expected charset. - To ime datoteke ne ustreza pričakovanemu naboru znakov. + Ime datoteke ne ustreza pričakovanemu naboru znakov. diff --git a/lib/symfony/validator/Resources/translations/validators.sr_Cyrl.xlf b/lib/symfony/validator/Resources/translations/validators.sr_Cyrl.xlf index 987474063..4aeba68fd 100644 --- a/lib/symfony/validator/Resources/translations/validators.sr_Cyrl.xlf +++ b/lib/symfony/validator/Resources/translations/validators.sr_Cyrl.xlf @@ -468,91 +468,91 @@ This value is not a valid Twig template. - Ова вредност није важећи Twig шаблон. + Ова вредност није валидан Twig шаблон. This file is not a valid video. - Ова датотека није важећи видео. + Ова датотека није валидан видео. The size of the video could not be detected. - Није било могуће утврдити величину видео снимка. + Величина видеа не може бити одређена. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Ширина видеа је превелика ({{ width }}px). Дозвољена максимална ширина је {{ max_width }}px. + Ширина видеа је превелика ({{ width }}px). Дозвољена максимална ширина је {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Ширина видеа је превише мала ({{ width }}px). Очекивана минимална ширина је {{ min_width }}px. + Ширина видеа је премала ({{ width }}px). Очекивана минимална ширина је {{ min_width }}px. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Висина видеа је превелика ({{ height }}px). Дозвољена максимална висина је {{ max_height }}px. + Висина видеа је превелика ({{ height }}px). Дозвољена максимална висина је {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Висина видеа је превише мала ({{ height }}px). Очекивана минимална висина је {{ min_height }}px. + Висина видеа је премала ({{ height }}px). Очекивана минимална висина је {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Видео има премало пиксела ({{ pixels }}). Очекивана минимална количина је {{ min_pixels }}. + Видео има премало пиксела ({{ pixels }}). Очекивани минимум је {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Видео има превише пиксела ({{ pixels }}). Очекивана максимална количина је {{ max_pixels }}. + Видео има превише пиксела ({{ pixels }}). Очекивани максимум је {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Однос слике видеа је превелик ({{ ratio }}). Дозвољени максимални однос је {{ max_ratio }}. + Однос страница видеа је превелик ({{ ratio }}). Дозвољени максимални однос је {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Однос стране видеа је превише мали ({{ ratio }}). Очекивани минимални однос је {{ min_ratio }}. + Однос страница видеа је премали ({{ ratio }}). Очекивани минимални однос је {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Видео је квадратног облика ({{ width }}x{{ height }}px). Квадратни видео записи нису дозвољени. + Видео је квадратног облика ({{ width }}x{{ height }}px). Квадратни видео записи нису дозвољени. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Видео је у водоравној оријентацији ({{ width }}x{{ height }} px). Водоравни видео записи нису дозвољени. + Видео је у водоравној оријентацији ({{ width }}x{{ height }}px). Водоравно оријентисани видео записи нису дозвољени. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Видео је у портрет оријентацији ({{ width }}x{{ height }}px). Видео снимци у портрет оријентацији нису дозвољени. + Видео је у портрет оријентацији ({{ width }}x{{ height }}px). Портретно оријентисани видео записи нису дозвољени. The video file is corrupted. - Видео датотека је оштећена. + Видео датотека је оштећена. The video contains multiple streams. Only one stream is allowed. - Видео садржи више токова. Дозвољен је само један ток. + Видео садржи више токова. Дозвољен је само један ток. Unsupported video codec "{{ codec }}". - Неподржан видео кодек „{{ codec }}“. + Неподржан видео кодек „{{ codec }}“. Unsupported video container "{{ container }}". - Неподржан видео контејнер "{{ container }}". + Неподржан видео контејнер „{{ container }}“. The image file is corrupted. - Датотека слике је оштећена. + Датотека слике је оштећена. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Слика има премало пиксела ({{ pixels }}). Очекивани минимални број је {{ min_pixels }}. + Слика има премало пиксела ({{ pixels }}). Очекивани минимум је {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Слика има превише пиксела ({{ pixels }}). Очекивани максимални број је {{ max_pixels }}. + Слика има превише пиксела ({{ pixels }}). Очекивани максимум је {{ max_pixels }}. This filename does not match the expected charset. - Ово име датотеке не одговара очекиваном скупу знакова. + Ово име датотеке не одговара очекиваном скупу знакова. diff --git a/lib/symfony/validator/Resources/translations/validators.tl.xlf b/lib/symfony/validator/Resources/translations/validators.tl.xlf index 7a25e79ea..fa806ab02 100644 --- a/lib/symfony/validator/Resources/translations/validators.tl.xlf +++ b/lib/symfony/validator/Resources/translations/validators.tl.xlf @@ -192,7 +192,7 @@ No temporary folder was configured in php.ini, or the configured folder does not exist. - Walang pansamantalang folder na na-configure sa php.ini, o ang naka-configure na folder ay hindi naroroon. + Walang pansamantalang folder na na-configure sa php.ini, o hindi umiiral ang na-configure na folder. Cannot write temporary file to disk. @@ -468,91 +468,91 @@ This value is not a valid Twig template. - Ang halagang ito ay hindi isang balidong Twig template. + Ang halagang ito ay hindi wastong Twig template. This file is not a valid video. - Ang file na ito ay hindi isang wastong video. + Ang file na ito ay hindi wastong video. The size of the video could not be detected. - Hindi matukoy ang laki ng video. + Hindi matukoy ang laki ng video. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Masyadong malaki ang lapad ng video ({{ width }}px). Ang pinahihintulutang pinakamaksimum na lapad ay {{ max_width }}px. + Masyadong malaki ang lapad ng video ({{ width }}px). Ang pinakamalaking pinapayagang lapad ay {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Masyadong maliit ang lapad ng video ({{ width }}px). Inaasahang minimum na lapad ay {{ min_width }}px. + Masyadong maliit ang lapad ng video ({{ width }}px). Ang inaasahang pinakamababang lapad ay {{ min_width }}px. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Sobrang taas ng video ({{ height }}px). Ang pinapahintulutang pinakamataas na taas ay {{ max_height }}px. + Masyadong malaki ang taas ng video ({{ height }}px). Ang pinakamalaking pinapayagang taas ay {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Masyadong maliit ang taas ng video ({{ height }}px). Inaasahang pinakamababang taas ay {{ min_height }}px. + Masyadong maliit ang taas ng video ({{ height }}px). Ang inaasahang pinakamababang taas ay {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Ang video ay may masyadong kaunting pixel ({{ pixels }}). Ang inaasahang pinakamababang dami ay {{ min_pixels }}. + Masyadong kakaunti ang mga pixel ng video ({{ pixels }}). Ang inaasahang pinakamababang bilang ay {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Ang video ay may masyadong maraming pixel ({{ pixels }}). Ang inaasahang pinakamataas na bilang ay {{ max_pixels }}. + Masyadong marami ang mga pixel ng video ({{ pixels }}). Ang inaasahang pinakamataas na bilang ay {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Masyadong malaki ang ratio ng video ({{ ratio }}). Ang pinahihintulutang pinakamataas na ratio ay {{ max_ratio }}. + Masyadong malaki ang ratio ng video ({{ ratio }}). Ang pinakamalaking pinapayagang ratio ay {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Masyadong maliit ang ratio ng video ({{ ratio }}). Ang inaasahang minimum na ratio ay {{ min_ratio }}. + Masyadong maliit ang ratio ng video ({{ ratio }}). Ang inaasahang pinakamababang ratio ay {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Ang video ay parisukat ({{ width }}x{{ height }}px). Hindi pinapayagan ang mga parisukat na video. + Parisukat ang video ({{ width }}x{{ height }}px). Hindi pinapayagan ang mga parisukat na video. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Ang video ay nasa landscape na oryentasyon ({{ width }}x{{ height }} px). Hindi pinapayagan ang mga landscape na video. + Naka-landscape ang video ({{ width }}x{{ height }}px). Hindi pinapayagan ang mga video na naka-landscape. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Ang video ay naka-portrait ({{ width }}x{{ height }}px). Hindi pinapayagan ang mga video na naka-portrait. + Naka-portrait ang video ({{ width }}x{{ height }}px). Hindi pinapayagan ang mga video na naka-portrait. The video file is corrupted. - Sira ang file ng video. + Sira ang video file. The video contains multiple streams. Only one stream is allowed. - May ilang stream ang video. Isa lamang na stream ang pinapayagan. + Maraming stream ang video. Iisang stream lamang ang pinapayagan. Unsupported video codec "{{ codec }}". - Hindi suportadong video codec "{{ codec }}". + Hindi suportadong video codec "{{ codec }}". Unsupported video container "{{ container }}". - Hindi suportadong lalagyan ng video "{{ container }}". + Hindi suportadong video container "{{ container }}". The image file is corrupted. - Ang file ng larawan ay sira. + Sira ang file ng larawan. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Masyadong kaunti ang pixel ng larawan ({{ pixels }}). Ang inaasahang pinakamababang dami ay {{ min_pixels }}. + Masyadong kakaunti ang mga pixel ng larawan ({{ pixels }}). Ang inaasahang pinakamababang bilang ay {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Ang larawan ay may sobrang daming pixel ({{ pixels }}). Ang inaasahang pinakamataas na dami ay {{ max_pixels }}. + Masyadong marami ang mga pixel ng larawan ({{ pixels }}). Ang inaasahang pinakamataas na bilang ay {{ max_pixels }}. This filename does not match the expected charset. - Ang pangalan ng file na ito ay hindi tumutugma sa inaasahang hanay ng mga character. + Ang pangalan ng file na ito ay hindi tumutugma sa inaasahang charset. diff --git a/lib/symfony/validator/Resources/translations/validators.uz.xlf b/lib/symfony/validator/Resources/translations/validators.uz.xlf index f86216abb..ff30d039b 100644 --- a/lib/symfony/validator/Resources/translations/validators.uz.xlf +++ b/lib/symfony/validator/Resources/translations/validators.uz.xlf @@ -136,7 +136,7 @@ This value is not a valid IP address. - Bu qiymat haqiqiy IP manzil emas. + Bu qiymat haqiqiy IP manzil emas. This value is not a valid language. @@ -192,7 +192,7 @@ No temporary folder was configured in php.ini, or the configured folder does not exist. - php.ini da vaqtinchalik katalog sozlanmagan, yoki sozlangan katalog mavjud emas. + php.ini da vaqtinchalik katalog sozlanmagan, yoki sozlangan katalog mavjud emas. Cannot write temporary file to disk. @@ -224,7 +224,7 @@ This value is not a valid International Bank Account Number (IBAN). - Bu qiymat haqiqiy Xalqaro Bank Hisob Raqami (IBAN) emas. + Bu qiymat haqiqiy Xalqaro Bank Hisob Raqami (IBAN) emas. This value is not a valid ISBN-10. @@ -312,7 +312,7 @@ This value is not a valid Business Identifier Code (BIC). - Bu qiymat haqiqiy Biznes Identifikatsiya Kodi (BIC) emas. + Bu qiymat haqiqiy Biznes Identifikatsiya Kodi (BIC) emas. Error @@ -320,7 +320,7 @@ This value is not a valid UUID. - Bu qiymat haqiqiy UUID emas. + Bu qiymat haqiqiy UUID emas. This value should be a multiple of {{ compared_value }}. @@ -432,127 +432,127 @@ The detected character encoding is invalid ({{ detected }}). Allowed encodings are {{ encodings }}. - Aniqlangan belgi kodlamasi yaroqsiz ({{ detected }}). Ruxsat etilgan kodlamalar {{ encodings }}. + Aniqlangan belgi kodlamasi yaroqsiz ({{ detected }}). Ruxsat etilgan kodlamalar {{ encodings }}. This value is not a valid MAC address. - Bu qiymat haqiqiy MAC manzil emas. + Bu qiymat haqiqiy MAC manzil emas. This URL is missing a top-level domain. - Bu URL yuqori darajali domenni o'z ichiga olmaydi. + Bu URL yuqori darajali domenni o'z ichiga olmaydi. This value is too short. It should contain at least one word.|This value is too short. It should contain at least {{ min }} words. - Bu qiymat juda qisqa. U kamida bitta so'z bo'lishi kerak.|Bu qiymat juda qisqa. U kamida {{ min }} so'z bo'lishi kerak. + Bu qiymat juda qisqa. U kamida bitta so'z bo'lishi kerak.|Bu qiymat juda qisqa. U kamida {{ min }} so'z bo'lishi kerak. This value is too long. It should contain one word.|This value is too long. It should contain {{ max }} words or less. - Bu qiymat juda uzun. U faqat bitta so'z bo'lishi kerak.|Bu qiymat juda uzun. U {{ max }} so'z yoki undan kam bo'lishi kerak. + Bu qiymat juda uzun. U faqat bitta so'z bo'lishi kerak.|Bu qiymat juda uzun. U {{ max }} so'z yoki undan kam bo'lishi kerak. This value does not represent a valid week in the ISO 8601 format. - Bu qiymat ISO 8601 formatida haqiqiy haftaga mos kelmaydi. + Bu qiymat ISO 8601 formatida haqiqiy haftaga mos kelmaydi. This value is not a valid week. - Bu qiymat haqiqiy hafta emas. + Bu qiymat haqiqiy hafta emas. This value should not be before week "{{ min }}". - Bu qiymat "{{ min }}" haftadan oldin bo'lmasligi kerak. + Bu qiymat "{{ min }}" haftadan oldin bo'lmasligi kerak. This value should not be after week "{{ max }}". - Bu qiymat "{{ max }}" haftadan keyin bo'lmasligi kerak. + Bu qiymat "{{ max }}" haftadan keyin bo'lmasligi kerak. This value is not a valid Twig template. - Bu qiymat yaroqli Twig shabloni emas. + Bu qiymat yaroqli Twig shabloni emas. This file is not a valid video. - Ushbu fayl yaroqli video emas. + Ushbu fayl yaroqli video emas. The size of the video could not be detected. - Videoning hajmini aniqlab bo‘lmadi. + Videoning hajmini aniqlab bo‘lmadi. The video width is too big ({{ width }}px). Allowed maximum width is {{ max_width }}px. - Video kengligi juda katta ({{ width }}px). Ruxsat etilgan maksimal kenglik {{ max_width }}px. + Video kengligi juda katta ({{ width }}px). Ruxsat etilgan maksimal kenglik {{ max_width }}px. The video width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px. - Video kengligi juda kichik ({{ width }}px). Kutilayotgan minimal kenglik {{ min_width }}px. + Video kengligi juda kichik ({{ width }}px). Kutilayotgan minimal kenglik {{ min_width }}px. The video height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px. - Video balandligi juda katta ({{ height }}px). Ruxsat etilgan maksimal balandlik {{ max_height }}px. + Video balandligi juda katta ({{ height }}px). Ruxsat etilgan maksimal balandlik {{ max_height }}px. The video height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px. - Video balandligi juda kichik ({{ height }}px). Kutilayotgan minimal balandlik {{ min_height }}px. + Video balandligi juda kichik ({{ height }}px). Kutilayotgan minimal balandlik {{ min_height }}px. The video has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Videoda piksellar soni juda kam ({{ pixels }}). Kutilgan minimal miqdor {{ min_pixels }}. + Videoda piksellar soni juda kam ({{ pixels }}). Kutilgan minimal miqdor {{ min_pixels }}. The video has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Videoda juda ko‘p piksellar bor ({{ pixels }}). Kutilayotgan maksimal miqdor {{ max_pixels }}. + Videoda juda ko‘p piksellar bor ({{ pixels }}). Kutilayotgan maksimal miqdor {{ max_pixels }}. The video ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}. - Video nisbati juda katta ({{ ratio }}). Ruxsat etilgan maksimal nisbat {{ max_ratio }}. + Video nisbati juda katta ({{ ratio }}). Ruxsat etilgan maksimal nisbat {{ max_ratio }}. The video ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}. - Video nisbati juda kichik ({{ ratio }}). Kutilayotgan minimal nisbat {{ min_ratio }}. + Video nisbati juda kichik ({{ ratio }}). Kutilayotgan minimal nisbat {{ min_ratio }}. The video is square ({{ width }}x{{ height }}px). Square videos are not allowed. - Video kvadrat ({{ width }}x{{ height }}px). Kvadrat videolarga ruxsat berilmaydi. + Video kvadrat ({{ width }}x{{ height }}px). Kvadrat videolarga ruxsat berilmaydi. The video is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented videos are not allowed. - Video gorizontal yo‘nalishda ({{ width }}x{{ height }} px). Gorizontal videolarga ruxsat berilmaydi. + Video gorizontal yo‘nalishda ({{ width }}x{{ height }} px). Gorizontal videolarga ruxsat berilmaydi. The video is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented videos are not allowed. - Video portret yoʻnalishda ({{ width }}x{{ height }}px). Portret yoʻnalishidagi videolarga ruxsat berilmaydi. + Video portret yoʻnalishda ({{ width }}x{{ height }}px). Portret yoʻnalishidagi videolarga ruxsat berilmaydi. The video file is corrupted. - Video fayli buzilgan. + Video fayli buzilgan. The video contains multiple streams. Only one stream is allowed. - Videoda bir nechta oqim mavjud. Faqat bitta oqimga ruxsat beriladi. + Videoda bir nechta oqim mavjud. Faqat bitta oqimga ruxsat beriladi. Unsupported video codec "{{ codec }}". - Qo‘llab-quvvatlanmaydigan video kodek "{{ codec }}". + Qo‘llab-quvvatlanmaydigan video kodek "{{ codec }}". Unsupported video container "{{ container }}". - Qo'llab-quvvatlanmaydigan video konteyner "{{ container }}". + Qo'llab-quvvatlanmaydigan video konteyner "{{ container }}". The image file is corrupted. - Rasm fayli buzilgan. + Rasm fayli buzilgan. The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels. - Tasvirda piksellar juda kam ({{ pixels }}). Kutilayotgan minimal miqdor {{ min_pixels }}. + Tasvirda piksellar juda kam ({{ pixels }}). Kutilayotgan minimal miqdor {{ min_pixels }}. The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels. - Tasvirda juda ko‘p piksel bor ({{ pixels }}). Kutilayotgan maksimal miqdor {{ max_pixels }}. + Tasvirda juda ko‘p piksel bor ({{ pixels }}). Kutilayotgan maksimal miqdor {{ max_pixels }}. This filename does not match the expected charset. - Bu fayl nomi kutilgan belgi to‘plamiga mos kelmaydi. + Bu fayl nomi kutilgan belgi to‘plamiga mos kelmaydi. diff --git a/lib/symfony/var-exporter/Internal/Hydrator.php b/lib/symfony/var-exporter/Internal/Hydrator.php index ebbceed05..b813f50e1 100644 --- a/lib/symfony/var-exporter/Internal/Hydrator.php +++ b/lib/symfony/var-exporter/Internal/Hydrator.php @@ -231,7 +231,11 @@ class Hydrator if (\PHP_VERSION_ID >= 80400 && !$propertyReflector->isAbstract() && $propertyReflector->getHooks()) { $notByRef->{$propertyReflector->name} = $propertyReflector->setRawValue(...); } elseif ($propertyReflector->isReadOnly()) { - $notByRef->{$propertyReflector->name} = true; + $notByRef->{$propertyReflector->name} = static function ($object, $value) use ($propertyReflector) { + if (!$propertyReflector->isInitialized($object)) { + $propertyReflector->setValue($object, $value); + } + }; } } diff --git a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig index a77ccb7be..c891abbc2 100644 --- a/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/lib/symfony/web-profiler-bundle/Resources/views/Profiler/toolbar_js.html.twig @@ -9,11 +9,11 @@ profiler_markup_version: 3, }) }} - + {{ include('@WebProfiler/Profiler/toolbar.css.twig') }} - + {# CAUTION: the contents of this file are processed by Twig before loading them as JavaScript source code. Always use '/*' comments instead of '//' comments to avoid impossible-to-debug side-effects #} @@ -21,7 +21,7 @@ if (typeof Sfjs === 'undefined' || typeof Sfjs.loadToolbar === 'undefined') { Sfjs = (function() { "use strict"; - + if ('classList' in document.documentElement) { var hasClass = function (el, cssClass) { return el.classList.contains(cssClass); }; var removeClass = function(el, cssClass) { el.classList.remove(cssClass); }; @@ -33,13 +33,13 @@ var addClass = function(el, cssClass) { if (!hasClass(el, cssClass)) { el.className += " " + cssClass; } }; var toggleClass = function(el, cssClass) { hasClass(el, cssClass) ? removeClass(el, cssClass) : addClass(el, cssClass); }; } - + var noop = function() {}; - + var profilerStorageKey = 'symfony/profiler/'; - + var addEventListener; - + var el = document.createElement('div'); if (!('addEventListener' in el)) { addEventListener = function (element, eventName, callback) { @@ -50,7 +50,7 @@ element.addEventListener(eventName, callback, false); }; } - + var request = function(url, onSuccess, onError, payload, options, tries) { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); options = options || {}; @@ -58,14 +58,14 @@ tries = tries || 1; /* this delays for 125, 375, 625, 875, and 1000, ... */ var delay = tries < 5 ? (tries - 0.5) * 250 : 1000; - + xhr.open(options.method || 'GET', url, true); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.onreadystatechange = function(state) { if (4 !== xhr.readyState) { return null; } - + if (xhr.status == 404 && options.retry && !options.stop) { setTimeout(function() { if (options.stop) { @@ -73,48 +73,48 @@ } request(url, onSuccess, onError, payload, options, tries + 1); }, delay); - + return null; } - + if (200 === xhr.status) { (onSuccess || noop)(xhr); } else { (onError || noop)(xhr); } }; - + if (options.onSend) { options.onSend(tries); } - + xhr.send(payload || ''); }; - + var getPreference = function(name) { if (!window.localStorage) { return null; } - + return localStorage.getItem(profilerStorageKey + name); }; - + var setPreference = function(name, value) { if (!window.localStorage) { return null; } - + localStorage.setItem(profilerStorageKey + name, value); }; - + var requestStack = []; - + var extractHeaders = function(xhr, stackElement) { /* Here we avoid to call xhr.getResponseHeader in order to */ /* prevent polluting the console with CORS security errors */ var allHeaders = xhr.getAllResponseHeaders(); var ret; - + if (ret = allHeaders.match(/^x-debug-token:\s+(.*)$/im)) { stackElement.profile = ret[1]; } @@ -126,7 +126,7 @@ stackElement.toolbarReplace = '1' === ret[1]; } }; - + var successStreak = 4; var pendingRequests = 0; var renderAjaxRequests = function() { @@ -135,12 +135,12 @@ return; } requestCounter.textContent = requestStack.length; - + var infoSpan = document.querySelector(".sf-toolbar-ajax-info"); if (infoSpan) { infoSpan.textContent = requestStack.length + ' AJAX request' + (requestStack.length !== 1 ? 's' : ''); } - + var ajaxToolbarPanel = document.querySelector('.sf-toolbar-block-ajax'); if (requestStack.length) { ajaxToolbarPanel.style.display = 'block'; @@ -157,45 +157,45 @@ removeClass(ajaxToolbarPanel, 'sf-toolbar-status-red'); } }; - + var startAjaxRequest = function(index) { var tbody = document.querySelector('.sf-toolbar-ajax-request-list'); if (!tbody) { return; } - + var nbOfAjaxRequest = tbody.rows.length; if (nbOfAjaxRequest >= 100) { tbody.deleteRow(0); } - + var request = requestStack[index]; pendingRequests++; var row = document.createElement('tr'); request.DOMNode = row; - + var requestNumberCell = document.createElement('td'); requestNumberCell.textContent = index + 1; row.appendChild(requestNumberCell); - + var profilerCell = document.createElement('td'); profilerCell.textContent = 'n/a'; row.appendChild(profilerCell); - + var methodCell = document.createElement('td'); methodCell.textContent = request.method; row.appendChild(methodCell); - + var typeCell = document.createElement('td'); typeCell.textContent = request.type; row.appendChild(typeCell); - + var statusCodeCell = document.createElement('td'); var statusCode = document.createElement('span'); statusCode.textContent = 'n/a'; statusCodeCell.appendChild(statusCode); row.appendChild(statusCodeCell); - + var pathCell = document.createElement('td'); pathCell.className = 'sf-ajax-request-url'; if ('GET' === request.method) { @@ -208,33 +208,33 @@ } pathCell.setAttribute('title', request.url); row.appendChild(pathCell); - + var durationCell = document.createElement('td'); durationCell.className = 'sf-ajax-request-duration'; durationCell.textContent = 'n/a'; row.appendChild(durationCell); - + request.liveDurationHandle = setInterval(function() { durationCell.textContent = (new Date() - request.start) + ' ms'; }, 100); - + row.className = 'sf-ajax-request sf-ajax-request-loading'; tbody.insertBefore(row, null); - + var toolbarInfo = document.querySelector('.sf-toolbar-block-ajax .sf-toolbar-info'); toolbarInfo.scrollTop = toolbarInfo.scrollHeight; - + renderAjaxRequests(); }; - + var finishAjaxRequest = function(index) { var request = requestStack[index]; clearInterval(request.liveDurationHandle); - + if (!request.DOMNode) { return; } - + if (request.toolbarReplace && !request.toolbarReplaceFinished && request.profile) { /* Flag as complete because finishAjaxRequest can be called multiple times. */ request.toolbarReplaceFinished = true; @@ -246,8 +246,11 @@ } } } - - pendingRequests--; + + if (pendingRequests > 0) { + pendingRequests--; + } + var row = request.DOMNode; /* Unpack the children from the row */ var profilerCell = row.children[1]; @@ -255,7 +258,7 @@ var statusCodeCell = row.children[4]; var statusCodeElem = statusCodeCell.children[0]; var durationCell = row.children[6]; - + if (request.error) { row.className = 'sf-ajax-request sf-ajax-request-error'; methodCell.className = 'sf-ajax-request-error'; @@ -264,7 +267,7 @@ row.className = 'sf-ajax-request sf-ajax-request-ok'; successStreak++; } - + if (request.statusCode) { if (request.statusCode < 300) { statusCodeElem.setAttribute('class', 'sf-toolbar-status'); @@ -277,11 +280,11 @@ } else { statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-red'); } - + if (request.duration) { durationCell.textContent = request.duration + ' ms'; } - + if (request.profilerUrl) { profilerCell.textContent = ''; var profilerLink = document.createElement('a'); @@ -289,10 +292,10 @@ profilerLink.textContent = request.profile; profilerCell.appendChild(profilerLink); } - + renderAjaxRequests(); }; - + {% if excluded_ajax_paths is defined %} if (window.fetch && window.fetch.polyfill === undefined) { var oldFetch = window.fetch; @@ -318,7 +321,7 @@ if (params && params.method !== undefined) { method = params.method; } - + var stackElement = { error: false, url: url, @@ -326,7 +329,7 @@ type: 'fetch', start: new Date() }; - + var idx = requestStack.push(stackElement) - 1; promise.then(function (r) { stackElement.duration = new Date() - stackElement.start; @@ -343,16 +346,16 @@ }); startAjaxRequest(idx); } - + return promise; }; } if (window.XMLHttpRequest && XMLHttpRequest.prototype.addEventListener) { var proxied = XMLHttpRequest.prototype.open; - + XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { var self = this; - + /* prevent logging AJAX calls to static and inline files, like templates */ var path = url; if (url.slice(0, 1) === '/') { @@ -363,7 +366,7 @@ else if (0 === url.indexOf('{{ (request.schemeAndHttpHost ~ request.basePath)|e('js') }}')) { path = url.slice({{ (request.schemeAndHttpHost ~ request.basePath)|length }}); } - + if (!path.match(new RegExp({{ excluded_ajax_paths|json_encode|raw }}))) { var stackElement = { error: false, @@ -372,54 +375,54 @@ type: 'xhr', start: new Date() }; - + var idx = requestStack.push(stackElement) - 1; - + this.addEventListener('readystatechange', function() { if (self.readyState == 4) { stackElement.duration = new Date() - stackElement.start; stackElement.error = self.status < 200 || self.status >= 400; stackElement.statusCode = self.status; extractHeaders(self, stackElement); - + finishAjaxRequest(idx); } }, false); - + startAjaxRequest(idx); } - + proxied.apply(this, Array.prototype.slice.call(arguments)); }; } {% endif %} - + return { hasClass: hasClass, - + removeClass: removeClass, - + addClass: addClass, - + toggleClass: toggleClass, - + getPreference: getPreference, - + setPreference: setPreference, - + addEventListener: addEventListener, - + request: request, - + renderAjaxRequests: renderAjaxRequests, - + getSfwdt: function(token) { return document.getElementById('sfwdt' + token); }, - + load: function(selector, url, onSuccess, onError, options) { var el = document.getElementById(selector); - + if (el && el.getAttribute('data-sfurl') !== url) { request( url, @@ -443,14 +446,14 @@ options ); } - + return this; }, - + showToolbar: function(token) { var sfwdt = this.getSfwdt(token); - removeClass(sfwdt, 'sf-display-none'); - + removeClass(sfwdt.parentNode, 'sf-display-none'); + if (getPreference('toolbar/displayState') == 'none') { document.getElementById('sfToolbarMainContent-' + token).style.display = 'none'; document.getElementById('sfToolbarClearer-' + token).style.display = 'none'; @@ -461,36 +464,36 @@ document.getElementById('sfMiniToolbar-' + token).style.display = 'none'; } }, - + hideToolbar: function(token) { var sfwdt = this.getSfwdt(token); - addClass(sfwdt, 'sf-display-none'); + addClass(sfwdt.parentNode, 'sf-display-none'); }, - + initToolbar: function(token) { this.showToolbar(token); - + var hideButton = document.getElementById('sfToolbarHideButton-' + token); var hideButtonSvg = hideButton.querySelector('svg'); hideButtonSvg.setAttribute('aria-hidden', 'true'); hideButtonSvg.setAttribute('focusable', 'false'); addEventListener(hideButton, 'click', function (event) { event.preventDefault(); - + var p = this.parentNode; p.style.display = 'none'; (p.previousElementSibling || p.previousSibling).style.display = 'none'; document.getElementById('sfMiniToolbar-' + token).style.display = 'block'; setPreference('toolbar/displayState', 'none'); }); - + var showButton = document.getElementById('sfToolbarMiniToggler-' + token); var showButtonSvg = showButton.querySelector('svg'); showButtonSvg.setAttribute('aria-hidden', 'true'); showButtonSvg.setAttribute('focusable', 'false'); addEventListener(showButton, 'click', function (event) { event.preventDefault(); - + var elem = this.parentNode; if (elem.style.display == 'none') { document.getElementById('sfToolbarMainContent-' + token).style.display = 'none'; @@ -501,54 +504,54 @@ document.getElementById('sfToolbarClearer-' + token).style.display = 'block'; elem.style.display = 'none' } - + setPreference('toolbar/displayState', 'block'); }); }, - + loadToolbar: function(token, newToken) { var that = this; var triesCounter = document.getElementById('sfLoadCounter-' + token); - + var options = { retry: true, onSend: function (count) { if (count === 3) { that.initToolbar(token); } - + if (triesCounter) { triesCounter.textContent = count; } }, }; - + var cancelButton = document.getElementById('sfLoadCancel-' + token); if (cancelButton) { addEventListener(cancelButton, 'click', function (event) { event.preventDefault(); - + options.stop = true; that.hideToolbar(token); }); } - + newToken = (newToken || token); - + this.load( 'sfwdt' + token, '{{ url("_wdt", { "token": "xxxxxx" })|escape('js') }}'.replace(/xxxxxx/, newToken), function(xhr, el) { var toolbarContent = document.getElementById('sfToolbarMainContent-' + newToken); - + /* Do nothing in the edge case where the toolbar has already been replaced with a new one */ if (!toolbarContent) { return; } - + /* Replace the ID, it has to match the new token */ toolbarContent.parentElement.id = 'sfwdt' + newToken; - + /* Evaluate in global scope scripts embedded inside the toolbar */ var i, scripts = [].slice.call(el.querySelectorAll('script')); for (i = 0; i < scripts.length; ++i) { @@ -556,15 +559,15 @@ eval.call({}, scripts[i].firstChild.nodeValue); } } - + el.style.display = -1 !== xhr.responseText.indexOf('sf-toolbarreset') ? 'block' : 'none'; - + if (el.style.display == 'none') { return; } - + that.initToolbar(newToken); - + /* Handle toolbar-info position */ var toolbarBlocks = [].slice.call(el.querySelectorAll('.sf-toolbar-block')); for (i = 0; i < toolbarBlocks.length; ++i) { @@ -574,11 +577,11 @@ var elementWidth = toolbarInfo.offsetWidth; var leftValue = (elementWidth + this.offsetLeft) - pageWidth; var rightValue = (elementWidth + (pageWidth - this.offsetLeft)) - pageWidth; - + /* Reset right and left value, useful on window resize */ toolbarInfo.style.right = ''; toolbarInfo.style.left = ''; - + if (elementWidth > pageWidth) { toolbarInfo.style.left = 0; } @@ -591,7 +594,7 @@ } }; } - + renderAjaxRequests(); addEventListener(document.querySelector('.sf-toolbar-ajax-clear'), 'click', function() { requestStack = []; @@ -605,10 +608,10 @@ }); addEventListener(document.querySelector('.sf-toolbar-block-ajax > .sf-toolbar-icon'), 'click', function (event) { event.preventDefault(); - + toggleClass(this.parentNode, 'hover'); }); - + var dumpInfo = document.querySelector('.sf-toolbar-block-dump .sf-toolbar-info'); if (null !== dumpInfo) { addEventListener(dumpInfo, 'sfbeforedumpcollapse', function () { @@ -628,32 +631,32 @@ An error occurred while loading the web debug toolbar. Open the web profiler.\ \ '; - sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar'); + sfwdt.parentElement.setAttribute('class', 'sf-toolbar sf-error-toolbar'); } }, options ); - + return this; }, - + toggle: function(selector, elOn, elOff) { var tmp = elOn.style.display, el = document.getElementById(selector); - + elOn.style.display = elOff.style.display; elOff.style.display = tmp; - + if (el) { el.style.display = 'none' === tmp ? 'none' : 'block'; } - + return this; }, }; })(); } - + Sfjs.loadToolbar('{{ token }}'); /*]]>*/ diff --git a/lib/tecnickcom/tcpdf/CHANGELOG.TXT b/lib/tecnickcom/tcpdf/CHANGELOG.TXT index 0ed8f5713..9c0d487bb 100644 --- a/lib/tecnickcom/tcpdf/CHANGELOG.TXT +++ b/lib/tecnickcom/tcpdf/CHANGELOG.TXT @@ -1,3 +1,9 @@ +6.11.2 (2026-03-03) + - Refactor setCompression(). + +6.11.1 (2026-03-03) + - Remove debug line preventing compression. + 6.11.0 (2026-03-01) - Updated copyright year. - Updated linked http urls to https. diff --git a/lib/tecnickcom/tcpdf/VERSION b/lib/tecnickcom/tcpdf/VERSION index 1de66e5ff..e18a34b9d 100644 --- a/lib/tecnickcom/tcpdf/VERSION +++ b/lib/tecnickcom/tcpdf/VERSION @@ -1 +1 @@ -6.11.0 +6.11.2 diff --git a/lib/tecnickcom/tcpdf/composer.json b/lib/tecnickcom/tcpdf/composer.json index 089bb5693..ac175a7f4 100644 --- a/lib/tecnickcom/tcpdf/composer.json +++ b/lib/tecnickcom/tcpdf/composer.json @@ -12,7 +12,7 @@ "barcodes" ], "homepage": "http://www.tcpdf.org/", - "version": "6.11.0", + "version": "6.11.2", "license": "LGPL-3.0-or-later", "authors": [ { diff --git a/lib/tecnickcom/tcpdf/include/tcpdf_static.php b/lib/tecnickcom/tcpdf/include/tcpdf_static.php index 6afddc57f..dc1572637 100644 --- a/lib/tecnickcom/tcpdf/include/tcpdf_static.php +++ b/lib/tecnickcom/tcpdf/include/tcpdf_static.php @@ -55,7 +55,7 @@ class TCPDF_STATIC { * Current TCPDF version. * @private static */ - private static $tcpdf_version = '6.11.0'; + private static $tcpdf_version = '6.11.2'; /** * String alias for total number of pages. diff --git a/lib/tecnickcom/tcpdf/tcpdf.php b/lib/tecnickcom/tcpdf/tcpdf.php index 36f992c53..cffe210d2 100644 --- a/lib/tecnickcom/tcpdf/tcpdf.php +++ b/lib/tecnickcom/tcpdf/tcpdf.php @@ -1,9 +1,9 @@ * @package com.tecnick.tcpdf * @author Nicola Asuni - * @version 6.11.0 + * @version 6.11.2 */ // TCPDF configuration @@ -128,7 +128,7 @@ require_once(dirname(__FILE__).'/include/tcpdf_static.php'); * TCPDF project (http://www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (http://www.fpdf.org), but now is almost entirely rewritten.
* @package com.tecnick.tcpdf * @brief PHP class for generating PDF documents without requiring external extensions. - * @version 6.11.0 + * @version 6.11.2 * @author Nicola Asuni - info@tecnick.com * @IgnoreAnnotation("protected") * @IgnoreAnnotation("public") @@ -2907,12 +2907,7 @@ class TCPDF { * @since 1.4 */ public function setCompression($compress=true) { - $this->compress = false; return; - if (function_exists('gzcompress')) { - if ($compress) { - $this->compress = true; - } - } + $this->compress = ($compress && function_exists('gzcompress')); } /** diff --git a/lib/tecnickcom/tcpdf/tools/tcpdf_addfont.php b/lib/tecnickcom/tcpdf/tools/tcpdf_addfont.php old mode 100644 new mode 100755 diff --git a/lib/twig/twig/CHANGELOG b/lib/twig/twig/CHANGELOG index cf47a7604..69b8ca7fd 100644 --- a/lib/twig/twig/CHANGELOG +++ b/lib/twig/twig/CHANGELOG @@ -1,3 +1,13 @@ +# 3.24.0 (2026-03-17) + + * Deprecate not implementing the `getOperatorTokens()` method in `ExpressionParserInterface` implementations + * Deprecate passing a non-`AbstractExpression` node to `Twig\Node\Expression\Binary\MatchesBinary` constructor + * Deprecate passing a non-`AbstractExpression` node to `Parser::setParent()` + * Add support for renaming variables in object destructuring (`{name: userName} = user`) + * Add `html_attr_relaxed` escaping strategy that preserves :, @, [, and ] for front-end framework attribute names + * Add support for short-circuiting in null-safe operator chains + * Add the `html_attr` function and `html_attr_merge` as well as `html_attr_type` filters + # 3.23.0 (2026-01-23) * Add `=` assignment operator (allows to set variables in expression or to replace the short-form of the set tag) diff --git a/lib/twig/twig/composer.json b/lib/twig/twig/composer.json index 366236637..788ebe708 100644 --- a/lib/twig/twig/composer.json +++ b/lib/twig/twig/composer.json @@ -32,7 +32,8 @@ "require-dev": { "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0", "psr/container": "^1.0|^2.0", - "phpstan/phpstan": "^2.0" + "phpstan/phpstan": "^2.0@stable", + "php-cs-fixer/shim": "^3.0@stable" }, "autoload": { "files": [ diff --git a/lib/twig/twig/splitsh.json b/lib/twig/twig/splitsh.json deleted file mode 100644 index f415dd8d4..000000000 --- a/lib/twig/twig/splitsh.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "subtrees": { - "twig-extra-bundle": "extra/twig-extra-bundle", - "cache-extra": "extra/cache-extra", - "cssinliner-extra": "extra/cssinliner-extra", - "html-extra": "extra/html-extra", - "inky-extra": "extra/inky-extra", - "intl-extra": "extra/intl-extra", - "markdown-extra": "extra/markdown-extra", - "string-extra": "extra/string-extra" - }, - "defaults": { - "git_constraint": "<1.8.2" - } -} diff --git a/lib/twig/twig/src/Environment.php b/lib/twig/twig/src/Environment.php index 2af647611..176b6aa5a 100644 --- a/lib/twig/twig/src/Environment.php +++ b/lib/twig/twig/src/Environment.php @@ -43,10 +43,10 @@ use Twig\TokenParser\TokenParserInterface; */ class Environment { - public const VERSION = '3.23.0'; - public const VERSION_ID = 32300; + public const VERSION = '3.24.0'; + public const VERSION_ID = 32400; public const MAJOR_VERSION = 3; - public const MINOR_VERSION = 23; + public const MINOR_VERSION = 24; public const RELEASE_VERSION = 0; public const EXTRA_VERSION = ''; diff --git a/lib/twig/twig/src/ExpressionParser/AbstractExpressionParser.php b/lib/twig/twig/src/ExpressionParser/AbstractExpressionParser.php index bc05bfa05..b8b963a1f 100644 --- a/lib/twig/twig/src/ExpressionParser/AbstractExpressionParser.php +++ b/lib/twig/twig/src/ExpressionParser/AbstractExpressionParser.php @@ -27,4 +27,9 @@ abstract class AbstractExpressionParser implements ExpressionParserInterface { return []; } + + public function getOperatorTokens(): array + { + return [$this->getName(), ...$this->getAliases()]; + } } diff --git a/lib/twig/twig/src/ExpressionParser/ExpressionParserInterface.php b/lib/twig/twig/src/ExpressionParser/ExpressionParserInterface.php index 86576aec4..2013a114e 100644 --- a/lib/twig/twig/src/ExpressionParser/ExpressionParserInterface.php +++ b/lib/twig/twig/src/ExpressionParser/ExpressionParserInterface.php @@ -11,6 +11,14 @@ namespace Twig\ExpressionParser; +/** + * @method list getOperatorTokens() Returns the operator token strings that this expression parser handles. + * These are the strings that should be recognized as operator tokens by the Lexer, + * and used to look up the parser in the registry. + * For most parsers, this returns the name and aliases. Parsers that don't handle + * operator tokens (like LiteralExpressionParser) should return an empty array. + * This method will be added to the interface in Twig 4.0. + */ interface ExpressionParserInterface { public function __toString(): string; diff --git a/lib/twig/twig/src/ExpressionParser/ExpressionParsers.php b/lib/twig/twig/src/ExpressionParser/ExpressionParsers.php index fb35a690e..7efaffc14 100644 --- a/lib/twig/twig/src/ExpressionParser/ExpressionParsers.php +++ b/lib/twig/twig/src/ExpressionParser/ExpressionParsers.php @@ -54,10 +54,9 @@ final class ExpressionParsers implements \IteratorAggregate // throw new \InvalidArgumentException(\sprintf('Precedence for "%s" must be between 0 and 512, got %d.', $parser->getName(), $parser->getPrecedence())); } $interface = $parser instanceof PrefixExpressionParserInterface ? PrefixExpressionParserInterface::class : InfixExpressionParserInterface::class; - $this->parsersByName[$interface][$parser->getName()] = $parser; $this->parsersByClass[$parser::class] = $parser; - foreach ($parser->getAliases() as $alias) { - $this->parsersByName[$interface][$alias] = $parser; + foreach (self::getOperatorTokensFor($parser) as $token) { + $this->parsersByName[$interface][$token] = $parser; } } @@ -90,9 +89,22 @@ final class ExpressionParsers implements \IteratorAggregate public function getIterator(): \Traversable { + $seen = []; foreach ($this->parsersByName as $parsers) { - // we don't yield the keys - yield from $parsers; + foreach ($parsers as $parser) { + $id = spl_object_id($parser); + if (!isset($seen[$id])) { + $seen[$id] = true; + yield $parser; + } + } + } + foreach ($this->parsersByClass as $parser) { + $id = spl_object_id($parser); + if (!isset($seen[$id])) { + $seen[$id] = true; + yield $parser; + } } } @@ -124,4 +136,20 @@ final class ExpressionParsers implements \IteratorAggregate return $this->precedenceChanges; } + + /** + * @internal + * + * @return array + */ + public static function getOperatorTokensFor(ExpressionParserInterface $parser): array + { + if (method_exists($parser, 'getOperatorTokens')) { + return $parser->getOperatorTokens(); + } + + trigger_deprecation('twig/twig', '3.24', 'Not implementing the "getOperatorTokens()" method in "%s" is deprecated. This method will be part of the "%s" interface in 4.0.', $parser::class, ExpressionParserInterface::class); + + return [$parser->getName(), ...$parser->getAliases()]; + } } diff --git a/lib/twig/twig/src/ExpressionParser/Infix/AssignmentExpressionParser.php b/lib/twig/twig/src/ExpressionParser/Infix/AssignmentExpressionParser.php index fa8c4f2b0..1f042845c 100644 --- a/lib/twig/twig/src/ExpressionParser/Infix/AssignmentExpressionParser.php +++ b/lib/twig/twig/src/ExpressionParser/Infix/AssignmentExpressionParser.php @@ -51,12 +51,12 @@ class AssignmentExpressionParser extends BinaryOperatorExpressionParser if ($left instanceof ArrayExpression) { if ($left->isSequence()) { return new SequenceDestructuringSetBinary($left, $right, $token->getLine()); - } else { - return new ObjectDestructuringSetBinary($left, $right, $token->getLine()); } - } else { - return new SetBinary($left, $right, $token->getLine()); + + return new ObjectDestructuringSetBinary($left, $right, $token->getLine()); } + + return new SetBinary($left, $right, $token->getLine()); } public function getDescription(): string diff --git a/lib/twig/twig/src/ExpressionParser/Prefix/GroupingExpressionParser.php b/lib/twig/twig/src/ExpressionParser/Prefix/GroupingExpressionParser.php index 5c6608da4..95a11762f 100644 --- a/lib/twig/twig/src/ExpressionParser/Prefix/GroupingExpressionParser.php +++ b/lib/twig/twig/src/ExpressionParser/Prefix/GroupingExpressionParser.php @@ -17,6 +17,7 @@ use Twig\ExpressionParser\ExpressionParserDescriptionInterface; use Twig\ExpressionParser\PrefixExpressionParserInterface; use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ListExpression; +use Twig\Node\Expression\Variable\AssignContextVariable; use Twig\Node\Expression\Variable\ContextVariable; use Twig\Parser; use Twig\Token; @@ -36,7 +37,7 @@ final class GroupingExpressionParser extends AbstractExpressionParser implements return $expr->setExplicitParentheses(); } - return new ListExpression([$expr], $token->getLine()); + return new ListExpression([self::toAssignContextVariable($expr)], $token->getLine()); } // determine if we are parsing an arrow function arguments @@ -58,7 +59,16 @@ final class GroupingExpressionParser extends AbstractExpressionParser implements throw new SyntaxError('A list of variables must be followed by an arrow.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); } - return new ListExpression($names, $token->getLine()); + return new ListExpression(array_map(self::toAssignContextVariable(...), $names), $token->getLine()); + } + + private static function toAssignContextVariable(AbstractExpression $expr): AssignContextVariable + { + if (!$expr instanceof ContextVariable) { + throw new SyntaxError('A list must only contain variables.', $expr->getTemplateLine(), $expr->getSourceContext()); + } + + return $expr instanceof AssignContextVariable ? $expr : new AssignContextVariable($expr->getAttribute('name'), $expr->getTemplateLine()); } public function getName(): string diff --git a/lib/twig/twig/src/ExpressionParser/Prefix/LiteralExpressionParser.php b/lib/twig/twig/src/ExpressionParser/Prefix/LiteralExpressionParser.php index da3805106..b467d1aa5 100644 --- a/lib/twig/twig/src/ExpressionParser/Prefix/LiteralExpressionParser.php +++ b/lib/twig/twig/src/ExpressionParser/Prefix/LiteralExpressionParser.php @@ -30,8 +30,6 @@ use Twig\Token; */ final class LiteralExpressionParser extends AbstractExpressionParser implements PrefixExpressionParserInterface, ExpressionParserDescriptionInterface { - private string $type = 'literal'; - public function parse(Parser $parser, Token $token): AbstractExpression { $stream = $parser->getStream(); @@ -41,41 +39,30 @@ final class LiteralExpressionParser extends AbstractExpressionParser implements switch ($token->getValue()) { case 'true': case 'TRUE': - $this->type = 'constant'; - return new ConstantExpression(true, $token->getLine()); case 'false': case 'FALSE': - $this->type = 'constant'; - return new ConstantExpression(false, $token->getLine()); case 'none': case 'NONE': case 'null': case 'NULL': - $this->type = 'constant'; - return new ConstantExpression(null, $token->getLine()); default: - $this->type = 'variable'; - return new ContextVariable($token->getValue(), $token->getLine()); } // no break case $token->test(Token::NUMBER_TYPE): $stream->next(); - $this->type = 'constant'; return new ConstantExpression($token->getValue(), $token->getLine()); case $token->test(Token::STRING_TYPE): case $token->test(Token::INTERPOLATION_START_TYPE): - $this->type = 'string'; - return $this->parseStringExpression($parser); case $token->test(Token::PUNCTUATION_TYPE): @@ -96,7 +83,6 @@ final class LiteralExpressionParser extends AbstractExpressionParser implements if (preg_match(Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { // in this context, string operators are variable names $stream->next(); - $this->type = 'variable'; return new ContextVariable($token->getValue(), $token->getLine()); } @@ -109,7 +95,12 @@ final class LiteralExpressionParser extends AbstractExpressionParser implements public function getName(): string { - return $this->type; + return 'literal'; + } + + public function getOperatorTokens(): array + { + return []; } public function getDescription(): string @@ -153,8 +144,6 @@ final class LiteralExpressionParser extends AbstractExpressionParser implements private function parseSequenceExpression(Parser $parser) { - $this->type = 'sequence'; - $stream = $parser->getStream(); $stream->expect(Token::OPERATOR_TYPE, '[', 'A sequence element was expected'); @@ -185,8 +174,6 @@ final class LiteralExpressionParser extends AbstractExpressionParser implements private function parseMappingExpression(Parser $parser) { - $this->type = 'mapping'; - $stream = $parser->getStream(); $stream->expect(Token::PUNCTUATION_TYPE, '{', 'A mapping element was expected'); diff --git a/lib/twig/twig/src/Extension/CoreExtension.php b/lib/twig/twig/src/Extension/CoreExtension.php index 345f40666..b89321ebe 100644 --- a/lib/twig/twig/src/Extension/CoreExtension.php +++ b/lib/twig/twig/src/Extension/CoreExtension.php @@ -134,7 +134,7 @@ final class CoreExtension extends AbstractExtension private $dateFormats = ['F j, Y H:i', '%d days']; private $numberFormat = [0, '.', ',']; - private $timezone = null; + private $timezone; /** * Sets the default format to be used by the date filter. @@ -1128,9 +1128,9 @@ final class CoreExtension extends AbstractExtension } if ((int) $bTrim == $bTrim) { return $a <=> (int) $bTrim; - } else { - return (float) $a <=> (float) $bTrim; } + + return (float) $a <=> (float) $bTrim; } if (\is_string($a) && \is_int($b)) { $aTrim = trim($a, " \t\n\r\v\f"); @@ -1139,9 +1139,9 @@ final class CoreExtension extends AbstractExtension } if ((int) $aTrim == $aTrim) { return (int) $aTrim <=> $b; - } else { - return (float) $aTrim <=> (float) $b; } + + return (float) $aTrim <=> (float) $b; } // float <=> string @@ -1179,7 +1179,7 @@ final class CoreExtension extends AbstractExtension */ public static function matches(string $regexp, ?string $str): int { - set_error_handler(function ($t, $m) use ($regexp) { + set_error_handler(static function ($t, $m) use ($regexp) { throw new RuntimeError(\sprintf('Regexp "%s" passed to "matches" is not valid', $regexp).substr($m, 12)); }); try { @@ -2148,7 +2148,7 @@ final class CoreExtension extends AbstractExtension */ public static function parseBlockFunction(Parser $parser, Node $fakeNode, $args, int $line): AbstractExpression { - $fakeFunction = new TwigFunction('block', fn ($name, $template = null) => null); + $fakeFunction = new TwigFunction('block', static fn ($name, $template = null) => null); $args = (new CallableArgumentsExtractor($fakeNode, $fakeFunction))->extractArguments($args); return new BlockReferenceExpression($args[0], $args[1] ?? null, $line); @@ -2159,7 +2159,7 @@ final class CoreExtension extends AbstractExtension */ public static function parseAttributeFunction(Parser $parser, Node $fakeNode, $args, int $line): AbstractExpression { - $fakeFunction = new TwigFunction('attribute', fn ($variable, $attribute, $arguments = null) => null); + $fakeFunction = new TwigFunction('attribute', static fn ($variable, $attribute, $arguments = null) => null); $args = (new CallableArgumentsExtractor($fakeNode, $fakeFunction))->extractArguments($args); /* diff --git a/lib/twig/twig/src/Lexer.php b/lib/twig/twig/src/Lexer.php index 508a79c02..e65f5bedc 100644 --- a/lib/twig/twig/src/Lexer.php +++ b/lib/twig/twig/src/Lexer.php @@ -13,6 +13,7 @@ namespace Twig; use Twig\Error\SyntaxError; +use Twig\ExpressionParser\ExpressionParsers; /** * @author Fabien Potencier @@ -527,7 +528,7 @@ class Lexer { $expressionParsers = []; foreach ($this->env->getExpressionParsers() as $expressionParser) { - $expressionParsers = array_merge($expressionParsers, [$expressionParser->getName()], $expressionParser->getAliases()); + $expressionParsers = array_merge($expressionParsers, ExpressionParsers::getOperatorTokensFor($expressionParser)); } $expressionParsers = array_combine($expressionParsers, array_map('strlen', $expressionParsers)); @@ -544,7 +545,7 @@ class Lexer // an operator that begins with a character must not have a dot or pipe before if (ctype_alpha($expressionParser[0])) { - $r = '(?getTemplateLine(), $names->getSourceContext()); - } - if ($names instanceof ContextVariable) { $names = new ListExpression([new AssignContextVariable($names->getAttribute('name'), $names->getTemplateLine())], $lineno); } + if (!$names instanceof ListExpression) { + throw new SyntaxError('The arrow function argument must be a list of variables or a single variable.', $names->getTemplateLine(), $names->getSourceContext()); + } + parent::__construct(['expr' => $expr, 'names' => $names], [], $lineno); } diff --git a/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php b/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php index 569dfde05..bd1f24f0c 100644 --- a/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php +++ b/lib/twig/twig/src/Node/Expression/Binary/MatchesBinary.php @@ -13,6 +13,7 @@ namespace Twig\Node\Expression\Binary; use Twig\Compiler; use Twig\Error\SyntaxError; +use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ConstantExpression; use Twig\Node\Expression\ReturnBoolInterface; use Twig\Node\Node; @@ -21,6 +22,13 @@ class MatchesBinary extends AbstractBinary implements ReturnBoolInterface { public function __construct(Node $left, Node $right, int $lineno) { + if (!$left instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.24', 'Passing a "%s" instance to "%s()" first argument is deprecated, pass an "AbstractExpression" instance instead.', $left::class, __METHOD__); + } + if (!$right instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.24', 'Passing a "%s" instance to "%s()" second argument is deprecated, pass an "AbstractExpression" instance instead.', $right::class, __METHOD__); + } + if ($right instanceof ConstantExpression) { $regexp = $right->getAttribute('value'); set_error_handler(static fn ($t, $m) => throw new SyntaxError(\sprintf('Regexp "%s" passed to "matches" is not valid: %s.', $regexp, substr($m, 14)), $lineno)); diff --git a/lib/twig/twig/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php b/lib/twig/twig/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php index 2c0853f65..b47c50fe8 100644 --- a/lib/twig/twig/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php +++ b/lib/twig/twig/src/Node/Expression/Binary/ObjectDestructuringSetBinary.php @@ -23,7 +23,8 @@ use Twig\Node\Node; */ class ObjectDestructuringSetBinary extends AbstractBinary { - private array $properties = []; + /** @var list */ + private array $mappings = []; /** * @param ArrayExpression $left The array expression containing object/mapping destructuring properties @@ -38,7 +39,11 @@ class ObjectDestructuringSetBinary extends AbstractBinary if (!$pair['value'] instanceof ContextVariable) { throw new SyntaxError(\sprintf('Cannot assign to "%s", only variables can be assigned in object/mapping destructuring.', $pair['value']::class), $lineno); } - $this->properties[] = $pair['value']->getAttribute('name'); + + $this->mappings[] = [ + 'property' => $pair['key']->getAttribute('value'), + 'variable' => $pair['value']->getAttribute('name'), + ]; } parent::__construct($left, $right, $lineno); @@ -48,18 +53,18 @@ class ObjectDestructuringSetBinary extends AbstractBinary { $compiler->addDebugInfo($this); $compiler->raw('['); - foreach ($this->properties as $i => $property) { + foreach ($this->mappings as $i => $mapping) { if ($i) { $compiler->raw(', '); } - $compiler->raw('$context[')->repr($property)->raw(']'); + $compiler->raw('$context[')->repr($mapping['variable'])->raw(']'); } $compiler->raw('] = ['); - foreach ($this->properties as $i => $property) { + foreach ($this->mappings as $i => $mapping) { if ($i) { $compiler->raw(', '); } - $compiler->raw('CoreExtension::getAttribute($this->env, $this->source, ')->subcompile($this->getNode('right'))->raw(', ')->repr($property)->raw(', [], \\Twig\\Template::ANY_CALL, false, false, false, ')->repr($this->getNode('right')->getTemplateLine())->raw(')'); + $compiler->raw('CoreExtension::getAttribute($this->env, $this->source, ')->subcompile($this->getNode('right'))->raw(', ')->repr($mapping['property'])->raw(', [], \\Twig\\Template::ANY_CALL, false, false, false, ')->repr($this->getNode('right')->getTemplateLine())->raw(')'); } $compiler->raw(']'); } diff --git a/lib/twig/twig/src/Node/Expression/CallExpression.php b/lib/twig/twig/src/Node/Expression/CallExpression.php index 330d82535..c97408f6d 100644 --- a/lib/twig/twig/src/Node/Expression/CallExpression.php +++ b/lib/twig/twig/src/Node/Expression/CallExpression.php @@ -24,7 +24,7 @@ use Twig\Util\ReflectionCallable; abstract class CallExpression extends AbstractExpression { - private $reflector = null; + private $reflector; /** * @return void @@ -213,9 +213,8 @@ abstract class CallExpression extends AbstractExpression } elseif ($callableParameter->isOptional()) { if (!$parameters) { break; - } else { - $missingArguments[] = $name; } + $missingArguments[] = $name; } else { throw new SyntaxError(\sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); } diff --git a/lib/twig/twig/src/Node/Expression/GetAttrExpression.php b/lib/twig/twig/src/Node/Expression/GetAttrExpression.php index f207b092c..cf6239517 100644 --- a/lib/twig/twig/src/Node/Expression/GetAttrExpression.php +++ b/lib/twig/twig/src/Node/Expression/GetAttrExpression.php @@ -36,7 +36,7 @@ class GetAttrExpression extends AbstractExpression implements SupportDefinedTest trigger_deprecation('twig/twig', '3.15', \sprintf('Not passing a "%s" instance as the "arguments" argument of the "%s" constructor is deprecated ("%s" given).', ArrayExpression::class, static::class, $arguments::class)); } - parent::__construct($nodes, ['type' => $type, 'ignore_strict_check' => false, 'optimizable' => !$nullSafe, 'null_safe' => $nullSafe], $lineno); + parent::__construct($nodes, ['type' => $type, 'ignore_strict_check' => false, 'optimizable' => !$nullSafe, 'null_safe' => $nullSafe, 'is_short_circuited' => false, 'var_name' => null], $lineno); } public function enableDefinedTest(): void @@ -50,7 +50,6 @@ class GetAttrExpression extends AbstractExpression implements SupportDefinedTest $env = $compiler->getEnvironment(); $arrayAccessSandbox = false; $nullSafe = $this->getAttribute('null_safe'); - $objectVar = null; // optimize array calls if ( @@ -99,18 +98,32 @@ class GetAttrExpression extends AbstractExpression implements SupportDefinedTest $this->getNode('node')->setAttribute('ignore_strict_check', true); } - if ($nullSafe) { - $objectVar = '$'.$compiler->getVarName(); + if (null === $nullSafeNode = $nullSafe ? $this : null) { + $node = $this->getNode('node'); + while ($node instanceof self) { + if ($node->getAttribute('null_safe')) { + $nullSafeNode = $node; + break; + } + $node = $node->getNode('node'); + } + } + + $isShortCircuited = false; + if (null !== $nullSafeNode && !$nullSafeNode->isShortCircuited()) { $compiler - ->raw('((null === ('.$objectVar.' = ') - ->subcompile($this->getNode('node')) + ->raw('((null === ('.$nullSafeNode->getVarName($compiler).' = ') + ->subcompile($nullSafeNode->getNode('node')) ->raw(')) ? null : '); + + $nullSafeNode->markAsShortCircuited(); + $isShortCircuited = true; } $compiler->raw('CoreExtension::getAttribute($this->env, $this->source, '); if ($nullSafe) { - $compiler->raw($objectVar); + $compiler->raw($this->getVarName($compiler)); } else { $compiler->subcompile($this->getNode('node')); } @@ -139,7 +152,7 @@ class GetAttrExpression extends AbstractExpression implements SupportDefinedTest $compiler->raw(')'); } - if ($nullSafe) { + if ($isShortCircuited) { $compiler->raw(')'); } } @@ -153,4 +166,23 @@ class GetAttrExpression extends AbstractExpression implements SupportDefinedTest $this->changeIgnoreStrictCheck($node->getNode('node')); } } + + private function markAsShortCircuited(): void + { + $this->setAttribute('is_short_circuited', true); + } + + private function isShortCircuited(): bool + { + return $this->getAttribute('is_short_circuited'); + } + + private function getVarName(Compiler $compiler): string + { + if (null === $this->getAttribute('var_name')) { + $this->setAttribute('var_name', $compiler->getVarName()); + } + + return '$'.$this->getAttribute('var_name'); + } } diff --git a/lib/twig/twig/src/Node/Expression/ListExpression.php b/lib/twig/twig/src/Node/Expression/ListExpression.php index dd7fc1f9c..9b23857fc 100644 --- a/lib/twig/twig/src/Node/Expression/ListExpression.php +++ b/lib/twig/twig/src/Node/Expression/ListExpression.php @@ -12,12 +12,12 @@ namespace Twig\Node\Expression; use Twig\Compiler; -use Twig\Node\Expression\Variable\ContextVariable; +use Twig\Node\Expression\Variable\AssignContextVariable; class ListExpression extends AbstractExpression { /** - * @param array $items + * @param array $items */ public function __construct(array $items, int $lineno) { diff --git a/lib/twig/twig/src/Node/Expression/MacroReferenceExpression.php b/lib/twig/twig/src/Node/Expression/MacroReferenceExpression.php index fd7f1e733..ba1d556b4 100644 --- a/lib/twig/twig/src/Node/Expression/MacroReferenceExpression.php +++ b/lib/twig/twig/src/Node/Expression/MacroReferenceExpression.php @@ -29,6 +29,16 @@ class MacroReferenceExpression extends AbstractExpression implements SupportDefi parent::__construct(['template' => $template, 'arguments' => $arguments], ['name' => $name], $lineno); } + public function __clone() + { + // The template node must not be deep-cloned because its name is + // lazily generated during compilation and must stay in sync with + // the AssignTemplateVariable that populates the $macros array. + $template = $this->nodes['template']; + parent::__clone(); + $this->nodes['template'] = $template; + } + public function compile(Compiler $compiler): void { if ($this->definedTest) { diff --git a/lib/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php b/lib/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php index 8cb5f7a39..b1aea0f36 100644 --- a/lib/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php +++ b/lib/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php @@ -54,6 +54,11 @@ final class SafeAnalysisNodeVisitor implements NodeVisitorInterface if (\in_array('html_attr', $bucket['value'], true)) { $bucket['value'][] = 'html'; + $bucket['value'][] = 'html_attr_relaxed'; + } + + if (\in_array('html_attr_relaxed', $bucket['value'], true)) { + $bucket['value'][] = 'html'; } return $bucket['value']; diff --git a/lib/twig/twig/src/Parser.php b/lib/twig/twig/src/Parser.php index af54f13b2..3553007a9 100644 --- a/lib/twig/twig/src/Parser.php +++ b/lib/twig/twig/src/Parser.php @@ -416,6 +416,10 @@ class Parser trigger_deprecation('twig/twig', '3.12', 'Passing "null" to "%s()" is deprecated.', __METHOD__); } + if (null !== $parent && !$parent instanceof AbstractExpression) { + trigger_deprecation('twig/twig', '3.24', 'Passing a "%s" instance to "%s()" is deprecated, pass an "AbstractExpression" instance instead.', $parent::class, __METHOD__); + } + if (null !== $this->parent) { throw new SyntaxError('Multiple extends tags are forbidden.', $parent->getTemplateLine(), $parent->getSourceContext()); } @@ -447,7 +451,7 @@ class Parser if (!$function) { if ($this->shouldIgnoreUnknownTwigCallables()) { - return new TwigFunction($name, fn () => ''); + return new TwigFunction($name, static fn () => ''); } $e = new SyntaxError(\sprintf('Unknown "%s" function.', $name), $line, $this->stream->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getFunctions())); @@ -476,7 +480,7 @@ class Parser } if (!$filter) { if ($this->shouldIgnoreUnknownTwigCallables()) { - return new TwigFilter($name, fn () => ''); + return new TwigFilter($name, static fn () => ''); } $e = new SyntaxError(\sprintf('Unknown "%s" filter.', $name), $line, $this->stream->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getFilters())); @@ -524,7 +528,7 @@ class Parser if (!$test) { if ($this->shouldIgnoreUnknownTwigCallables()) { - return new TwigTest($name, fn () => ''); + return new TwigTest($name, static fn () => ''); } $e = new SyntaxError(\sprintf('Unknown "%s" test.', $name), $line, $this->stream->getSourceContext()); $e->addSuggestions($name, array_keys($this->env->getTests())); diff --git a/lib/twig/twig/src/Runtime/EscaperRuntime.php b/lib/twig/twig/src/Runtime/EscaperRuntime.php index f686e19f0..f4a7023c7 100644 --- a/lib/twig/twig/src/Runtime/EscaperRuntime.php +++ b/lib/twig/twig/src/Runtime/EscaperRuntime.php @@ -124,7 +124,7 @@ final class EscaperRuntime implements RuntimeExtensionInterface } $string = (string) $string; - } elseif (\in_array($strategy, ['html', 'js', 'css', 'html_attr', 'url'], true)) { + } elseif (\in_array($strategy, ['html', 'js', 'css', 'html_attr', 'html_attr_relaxed', 'url'], true)) { // we return the input as is (which can be of any type) return $string; } @@ -191,7 +191,7 @@ final class EscaperRuntime implements RuntimeExtensionInterface throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); } - $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', function ($matches) { + $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', static function ($matches) { $char = $matches[0]; /* @@ -243,7 +243,7 @@ final class EscaperRuntime implements RuntimeExtensionInterface throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); } - $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', function ($matches) { + $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', static function ($matches) { $char = $matches[0]; return \sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : mb_ord($char, 'UTF-8')); @@ -256,6 +256,7 @@ final class EscaperRuntime implements RuntimeExtensionInterface return $string; case 'html_attr': + case 'html_attr_relaxed': if ('UTF-8' !== $charset) { $string = $this->convertEncoding($string, 'UTF-8', $charset); } @@ -264,7 +265,12 @@ final class EscaperRuntime implements RuntimeExtensionInterface throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); } - $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', function ($matches) { + $regex = match ($strategy) { + 'html_attr' => '#[^a-zA-Z0-9,\.\-_]#Su', + 'html_attr_relaxed' => '#[^a-zA-Z0-9,\.\-_:@\[\]]#Su', + }; + + $string = preg_replace_callback($regex, static function ($matches) { /** * This function is adapted from code coming from Zend Framework. * @@ -323,7 +329,7 @@ final class EscaperRuntime implements RuntimeExtensionInterface return $this->escapers[$strategy]($string, $charset); } - $validStrategies = implode('", "', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($this->escapers))); + $validStrategies = implode('", "', array_merge(['html', 'js', 'url', 'css', 'html_attr', 'html_attr_relaxed'], array_keys($this->escapers))); throw new RuntimeError(\sprintf('Invalid escaping strategy "%s" (valid ones: "%s").', $strategy, $validStrategies)); } diff --git a/lib/twig/twig/src/Template.php b/lib/twig/twig/src/Template.php index c37209287..37f8a1f03 100644 --- a/lib/twig/twig/src/Template.php +++ b/lib/twig/twig/src/Template.php @@ -158,7 +158,7 @@ abstract class Template if ($this->env->isDebug()) { ob_start(); } else { - ob_start(function () { return ''; }); + ob_start(static function () { return ''; }); } $this->displayParentBlock($name, $context, $blocks); @@ -193,7 +193,7 @@ abstract class Template if ($this->env->isDebug()) { ob_start(); } else { - ob_start(function () { return ''; }); + ob_start(static function () { return ''; }); } try { $this->displayBlock($name, $context, $blocks, $useBlocks); @@ -367,7 +367,7 @@ abstract class Template if ($this->env->isDebug()) { ob_start(); } else { - ob_start(function () { return ''; }); + ob_start(static function () { return ''; }); } try { $this->display($context); diff --git a/lib/twig/twig/src/Util/DeprecationCollector.php b/lib/twig/twig/src/Util/DeprecationCollector.php index 0ea26ed4b..64cbba5a3 100644 --- a/lib/twig/twig/src/Util/DeprecationCollector.php +++ b/lib/twig/twig/src/Util/DeprecationCollector.php @@ -54,7 +54,7 @@ final class DeprecationCollector public function collect(\Traversable $iterator): array { $deprecations = []; - set_error_handler(function ($type, $msg) use (&$deprecations) { + set_error_handler(static function ($type, $msg) use (&$deprecations) { if (\E_USER_DEPRECATED === $type) { $deprecations[] = $msg; } diff --git a/setup/setuputils.class.inc.php b/setup/setuputils.class.inc.php index c44318ee1..b6ce04ef1 100644 --- a/setup/setuputils.class.inc.php +++ b/setup/setuputils.class.inc.php @@ -104,7 +104,7 @@ class CheckResult class SetupUtils { // -- Minimum versions (requirements : forbids installation if not met) - public const PHP_MIN_VERSION = '8.1.0'; + public const PHP_MIN_VERSION = '8.2.0'; public const MYSQL_MIN_VERSION = '5.7.0'; // 5.6 is no longer supported public const MYSQL_NOT_VALIDATED_VERSION = ''; // MySQL 8 is now OK (N°2010 in 2.7.0) but has no query cache so mind the perf on large volumes !