diff --git a/composer.json b/composer.json index d49daf9..34b13b7 100644 --- a/composer.json +++ b/composer.json @@ -25,15 +25,17 @@ "league/openapi-psr7-validator": "^0.22.0", "nelmio/api-doc-bundle": "^5.8", "nyholm/psr7": "^1.8", - "symfony/dependency-injection": "^7.3", - "symfony/framework-bundle": "^7.3", - "symfony/messenger": "^7.3", - "symfony/psr-http-message-bridge": "^7.3", - "symfony/serializer": "^7.3", - "symfony/validator": "^7.3" + "symfony/dependency-injection": "^7.3 || ^8.0", + "symfony/framework-bundle": "^7.3 || ^8.0", + "symfony/messenger": "^7.3 || ^8.0", + "symfony/property-access": "^7.3 || ^8.0", + "symfony/psr-http-message-bridge": "^7.3 || ^8.0", + "symfony/serializer": "^7.3 || ^8.0", + "symfony/validator": "^7.3 || ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.91", + "nyholm/symfony-bundle-test": "^3.0", "phpstan/extension-installer": "^1.4", "phpstan/phpstan": "^2.1", "phpstan/phpstan-phpunit": "^2.0", @@ -52,6 +54,8 @@ }, "scripts": { "test": "./vendor/bin/simple-phpunit", + "test:unit": "./vendor/bin/simple-phpunit --filter Unit", + "test:functional": "./vendor/bin/simple-phpunit --filter Functional", "check": [ "@cs-fixer", "@phpstan" diff --git a/composer.lock b/composer.lock index 5497f3e..f450110 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": "96b2ae5fe2b0935dd62375d826549cb9", + "content-hash": "03a22b91201eb01141880e3448228086", "packages": [ { "name": "devizzent/cebe-php-openapi", @@ -84,29 +84,29 @@ }, { "name": "doctrine/deprecations", - "version": "1.1.5", + "version": "1.1.6", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "conflict": { - "phpunit/phpunit": "<=7.5 || >=13" + "phpunit/phpunit": "<=7.5 || >=14" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^12 || ^13", - "phpstan/phpstan": "1.4.10 || 2.1.11", + "doctrine/coding-standard": "^9 || ^12 || ^14", + "phpstan/phpstan": "1.4.10 || 2.1.30", "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0", "psr/log": "^1 || ^2 || ^3" }, "suggest": { @@ -126,9 +126,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + "source": "https://github.com/doctrine/deprecations/tree/1.1.6" }, - "time": "2025-04-07T20:06:18+00:00" + "time": "2026-02-07T07:09:04+00:00" }, { "name": "justinrainbow/json-schema", @@ -524,43 +524,45 @@ }, { "name": "nelmio/api-doc-bundle", - "version": "v5.8.1", + "version": "v5.9.4", "source": { "type": "git", "url": "https://github.com/nelmio/NelmioApiDocBundle.git", - "reference": "16e139b812320dc33c971dc21627068fcc1ed34c" + "reference": "e651ed9764892c5637afd6ffe55e13bf8bd63033" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/16e139b812320dc33c971dc21627068fcc1ed34c", - "reference": "16e139b812320dc33c971dc21627068fcc1ed34c", + "url": "https://api.github.com/repos/nelmio/NelmioApiDocBundle/zipball/e651ed9764892c5637afd6ffe55e13bf8bd63033", + "reference": "e651ed9764892c5637afd6ffe55e13bf8bd63033", "shasum": "" }, "require": { "php": ">=8.2", - "phpdocumentor/reflection-docblock": "^5.0", - "phpdocumentor/type-resolver": "^1.8.2", + "phpdocumentor/reflection-docblock": "^5.0 || ^6.0", + "phpdocumentor/type-resolver": "^1.8.2 || ^2.0", "psr/cache": "^1.0 || ^2.0 || ^3.0", "psr/container": "^1.0 || ^2.0", "psr/log": "^1.0 || ^2.0 || ^3.0", - "symfony/config": "^6.4 || ^7.2", - "symfony/console": "^6.4 || ^7.2", - "symfony/dependency-injection": "^6.4 || ^7.2", + "symfony/config": "^6.4 || ^7.2 || ^8.0", + "symfony/console": "^6.4 || ^7.2 || ^8.0", + "symfony/dependency-injection": "^6.4 || ^7.2 || ^8.0", "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/framework-bundle": "^6.4 || ^7.2", - "symfony/http-foundation": "^6.4 || ^7.2", - "symfony/http-kernel": "^6.4 || ^7.2", - "symfony/options-resolver": "^6.4 || ^7.2", - "symfony/property-info": "^6.4 || ^7.2", - "symfony/routing": "^6.4 || ^7.2", - "symfony/type-info": "^7.2", + "symfony/framework-bundle": "^6.4 || ^7.2 || ^8.0", + "symfony/http-foundation": "^6.4 || ^7.2 || ^8.0", + "symfony/http-kernel": "^6.4 || ^7.2 || ^8.0", + "symfony/options-resolver": "^6.4 || ^7.2 || ^8.0", + "symfony/property-info": "^6.4 || ^7.2 || ^8.0", + "symfony/routing": "^6.4 || ^7.2 || ^8.0", + "symfony/type-info": "^7.2 || ^8.0", "zircote/swagger-php": "^4.11.1 || ^5.0" }, "conflict": { + "symfony/property-info": "6.4.32 || 7.3.10 || 7.4.4 || 8.0.4", "zircote/swagger-php": "4.8.7 || 5.5.0" }, "require-dev": { - "api-platform/core": "^3.2", + "api-platform/core": "^3.2 || ^4.0", + "doctrine/inflector": "^2.0", "friendsofphp/php-cs-fixer": "^3.52", "friendsofsymfony/rest-bundle": "^3.2.0", "jms/serializer": "^3.32", @@ -570,25 +572,22 @@ "phpstan/phpstan-strict-rules": "^2.0", "phpstan/phpstan-symfony": "^2.0", "phpunit/phpunit": "^10.5", - "symfony/asset": "^6.4 || ^7.2", - "symfony/browser-kit": "^6.4 || ^7.2", - "symfony/cache": "^6.4 || ^7.2", - "symfony/dom-crawler": "^6.4 || ^7.2", - "symfony/expression-language": "^6.4 || ^7.2", - "symfony/finder": "^6.4 || ^7.2", - "symfony/form": "^6.4 || ^7.2", - "symfony/phpunit-bridge": "^6.4 || ^7.2", - "symfony/property-access": "^6.4 || ^7.2", - "symfony/security-csrf": "^6.4 || ^7.2", - "symfony/security-http": "^6.4 || ^7.2", - "symfony/serializer": "^6.4 || ^7.2", - "symfony/stopwatch": "^6.4 || ^7.2", - "symfony/templating": "^6.4 || ^7.2", - "symfony/translation": "^6.4 || ^7.2", - "symfony/twig-bundle": "^6.4 || ^7.2", - "symfony/uid": "^6.4 || ^7.2", - "symfony/validator": "^6.4 || ^7.2", - "willdurand/hateoas-bundle": "^2.7", + "symfony/asset": "^6.4 || ^7.2 || ^8.0", + "symfony/browser-kit": "^6.4 || ^7.2 || ^8.0", + "symfony/cache": "^6.4 || ^7.2 || ^8.0", + "symfony/dom-crawler": "^6.4 || ^7.2 || ^8.0", + "symfony/expression-language": "^6.4 || ^7.2 || ^8.0", + "symfony/finder": "^6.4 || ^7.2 || ^8.0", + "symfony/form": "^6.4 || ^7.2 || ^8.0", + "symfony/phpunit-bridge": "^6.4 || ^7.2 || ^8.0", + "symfony/security-csrf": "^6.4 || ^7.2 || ^8.0", + "symfony/security-http": "^6.4 || ^7.2 || ^8.0", + "symfony/serializer": "^6.4 || ^7.2 || ^8.0", + "symfony/translation": "^6.4 || ^7.2 || ^8.0", + "symfony/twig-bundle": "^6.4 || ^7.2 || ^8.0", + "symfony/uid": "^6.4 || ^7.2 || ^8.0", + "symfony/validator": "^6.4 || ^7.2 || ^8.0", + "willdurand/hateoas-bundle": "^2.7 || ^3.0", "willdurand/negotiation": "^3.0" }, "suggest": { @@ -636,7 +635,7 @@ ], "support": { "issues": "https://github.com/nelmio/NelmioApiDocBundle/issues", - "source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v5.8.1" + "source": "https://github.com/nelmio/NelmioApiDocBundle/tree/v5.9.4" }, "funding": [ { @@ -644,7 +643,7 @@ "type": "github" } ], - "time": "2025-11-14T20:06:10+00:00" + "time": "2026-02-20T14:52:12+00:00" }, { "name": "nikic/php-parser", @@ -837,16 +836,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.6", + "version": "6.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8" + "reference": "2f5cbed597cb261d1ea458f3da3a9ad32e670b1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/5cee1d3dfc2d2aa6599834520911d246f656bcb8", - "reference": "5cee1d3dfc2d2aa6599834520911d246f656bcb8", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/2f5cbed597cb261d1ea458f3da3a9ad32e670b1e", + "reference": "2f5cbed597cb261d1ea458f3da3a9ad32e670b1e", "shasum": "" }, "require": { @@ -854,8 +853,8 @@ "ext-filter": "*", "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7|^2.0", + "phpdocumentor/type-resolver": "^2.0", + "phpstan/phpdoc-parser": "^2.0", "webmozart/assert": "^1.9.1 || ^2" }, "require-dev": { @@ -865,7 +864,8 @@ "phpstan/phpstan-mockery": "^1.1", "phpstan/phpstan-webmozart-assert": "^1.2", "phpunit/phpunit": "^9.5", - "psalm/phar": "^5.26" + "psalm/phar": "^5.26", + "shipmonk/dead-code-detector": "^0.5.1" }, "type": "library", "extra": { @@ -895,44 +895,44 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.6" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/6.0.1" }, - "time": "2025-12-22T21:13:58+00:00" + "time": "2026-01-20T15:30:42+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.12.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195" + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195", - "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/327a05bbee54120d4786a0dc67aad30226ad4cf9", + "reference": "327a05bbee54120d4786a0dc67aad30226ad4cf9", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", + "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.18|^2.0" + "phpstan/phpdoc-parser": "^2.0" }, "require-dev": { "ext-tokenizer": "*", "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" + "psalm/phar": "^4" }, "type": "library", "extra": { "branch-alias": { - "dev-1.x": "1.x-dev" + "dev-1.x": "1.x-dev", + "dev-2.x": "2.x-dev" } }, "autoload": { @@ -953,22 +953,22 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/2.0.0" }, - "time": "2025-11-21T15:09:14+00:00" + "time": "2026-01-06T21:53:42+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.0", + "version": "2.3.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495" + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1e0cd5370df5dd2e556a36b9c62f62e555870495", - "reference": "1e0cd5370df5dd2e556a36b9c62f62e555870495", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/a004701b11273a26cd7955a61d67a7f1e525a45a", + "reference": "a004701b11273a26cd7955a61d67a7f1e525a45a", "shasum": "" }, "require": { @@ -1000,9 +1000,9 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.0" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.2" }, - "time": "2025-08-30T15:50:23+00:00" + "time": "2026-01-25T14:56:51+00:00" }, { "name": "psr/cache", @@ -1655,32 +1655,30 @@ }, { "name": "symfony/cache", - "version": "v7.3.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "1277a1ec61c8d93ea61b2a59738f1deb9bfb6701" + "reference": "59184fa14658d7724cd9b8743d91c1b1aa618bff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/1277a1ec61c8d93ea61b2a59738f1deb9bfb6701", - "reference": "1277a1ec61c8d93ea61b2a59738f1deb9bfb6701", + "url": "https://api.github.com/repos/symfony/cache/zipball/59184fa14658d7724cd9b8743d91c1b1aa618bff", + "reference": "59184fa14658d7724cd9b8743d91c1b1aa618bff", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^3.6", - "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "conflict": { - "doctrine/dbal": "<3.6", - "symfony/dependency-injection": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/var-dumper": "<6.4" + "doctrine/dbal": "<4.3", + "ext-redis": "<6.1", + "ext-relay": "<0.12.1" }, "provide": { "psr/cache-implementation": "2.0|3.0", @@ -1689,16 +1687,16 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/dbal": "^3.6|^4", + "doctrine/dbal": "^4.3", "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/filesystem": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/clock": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/filesystem": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -1733,7 +1731,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.3.6" + "source": "https://github.com/symfony/cache/tree/v8.0.6" }, "funding": [ { @@ -1753,7 +1751,7 @@ "type": "tidelift" } ], - "time": "2025-10-30T13:22:58+00:00" + "time": "2026-02-21T23:29:37+00:00" }, { "name": "symfony/cache-contracts", @@ -1833,22 +1831,21 @@ }, { "name": "symfony/clock", - "version": "v7.3.0", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", - "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "url": "https://api.github.com/repos/symfony/clock/zipball/832119f9b8dbc6c8e6f65f30c5969eca1e88764f", + "reference": "832119f9b8dbc6c8e6f65f30c5969eca1e88764f", "shasum": "" }, "require": { - "php": ">=8.2", - "psr/clock": "^1.0", - "symfony/polyfill-php83": "^1.28" + "php": ">=8.4", + "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -1887,7 +1884,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.3.0" + "source": "https://github.com/symfony/clock/tree/v8.0.0" }, "funding": [ { @@ -1898,43 +1895,46 @@ "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": "2024-09-25T14:21:43+00:00" + "time": "2025-11-12T15:46:48+00:00" }, { "name": "symfony/config", - "version": "v7.3.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "9d18eba95655a3152ae4c1d53c6cc34eb4d4a0b7" + "reference": "94ea198de42f93dffa920a098cac3961a82e63b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/9d18eba95655a3152ae4c1d53c6cc34eb4d4a0b7", - "reference": "9d18eba95655a3152ae4c1d53c6cc34eb4d4a0b7", + "url": "https://api.github.com/repos/symfony/config/zipball/94ea198de42f93dffa920a098cac3961a82e63b7", + "reference": "94ea198de42f93dffa920a098cac3961a82e63b7", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^7.1", - "symfony/polyfill-ctype": "~1.8" + "symfony/filesystem": "^7.4|^8.0", + "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/finder": "<6.4", "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^6.4|^7.0" + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -1962,7 +1962,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/v7.3.6" + "source": "https://github.com/symfony/config/tree/v8.0.6" }, "funding": [ { @@ -1982,51 +1982,43 @@ "type": "tidelift" } ], - "time": "2025-11-02T08:04:43+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/console", - "version": "v7.3.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a" + "reference": "488285876e807a4777f074041d8bb508623419fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", - "reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a", + "url": "https://api.github.com/repos/symfony/console/zipball/488285876e807a4777f074041d8bb508623419fa", + "reference": "488285876e807a4777f074041d8bb508623419fa", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^7.2" - }, - "conflict": { - "symfony/dependency-injection": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/event-dispatcher": "<6.4", - "symfony/lock": "<6.4", - "symfony/process": "<6.4" + "symfony/string": "^7.4|^8.0" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2060,7 +2052,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.3.6" + "source": "https://github.com/symfony/console/tree/v8.0.6" }, "funding": [ { @@ -2080,43 +2072,40 @@ "type": "tidelift" } ], - "time": "2025-11-04T01:21:42+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.3.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "98af8bb46c56aedd9dd5a7f0414fc72bf2dcfe69" + "reference": "edd98864a7b9eaaa10f389bd414e7d9e816bb59d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/98af8bb46c56aedd9dd5a7f0414fc72bf2dcfe69", - "reference": "98af8bb46c56aedd9dd5a7f0414fc72bf2dcfe69", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/edd98864a7b9eaaa10f389bd414e7d9e816bb59d", + "reference": "edd98864a7b9eaaa10f389bd414e7d9e816bb59d", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/service-contracts": "^3.5", - "symfony/var-exporter": "^6.4.20|^7.2.5" + "symfony/service-contracts": "^3.6", + "symfony/var-exporter": "^7.4|^8.0" }, "conflict": { - "ext-psr": "<1.1|>=2", - "symfony/config": "<6.4", - "symfony/finder": "<6.4", - "symfony/yaml": "<6.4" + "ext-psr": "<1.1|>=2" }, "provide": { "psr/container-implementation": "1.1|2.0", "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/config": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2144,7 +2133,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/v7.3.6" + "source": "https://github.com/symfony/dependency-injection/tree/v8.0.6" }, "funding": [ { @@ -2164,7 +2153,7 @@ "type": "tidelift" } ], - "time": "2025-10-31T10:11:11+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2235,32 +2224,32 @@ }, { "name": "symfony/error-handler", - "version": "v7.3.6", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "bbe40bfab84323d99dab491b716ff142410a92a8" + "reference": "7620b97ec0ab1d2d6c7fb737aa55da411bea776a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/bbe40bfab84323d99dab491b716ff142410a92a8", - "reference": "bbe40bfab84323d99dab491b716ff142410a92a8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/7620b97ec0ab1d2d6c7fb737aa55da411bea776a", + "reference": "7620b97ec0ab1d2d6c7fb737aa55da411bea776a", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/polyfill-php85": "^1.32", + "symfony/var-dumper": "^7.4|^8.0" }, "conflict": { - "symfony/deprecation-contracts": "<2.5", - "symfony/http-kernel": "<6.4" + "symfony/deprecation-contracts": "<2.5" }, "require-dev": { - "symfony/console": "^6.4|^7.0", + "symfony/console": "^7.4|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ @@ -2292,7 +2281,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/v7.3.6" + "source": "https://github.com/symfony/error-handler/tree/v8.0.4" }, "funding": [ { @@ -2312,28 +2301,28 @@ "type": "tidelift" } ], - "time": "2025-10-31T19:12:50+00:00" + "time": "2026-01-23T11:07:10+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.3.3", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", - "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99301401da182b6cfaa4700dbe9987bb75474b47", + "reference": "99301401da182b6cfaa4700dbe9987bb75474b47", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<6.4", + "symfony/security-http": "<7.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -2342,13 +2331,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/error-handler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/stopwatch": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2376,7 +2366,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/v7.3.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v8.0.4" }, "funding": [ { @@ -2396,7 +2386,7 @@ "type": "tidelift" } ], - "time": "2025-08-13T11:49:31+00:00" + "time": "2026-01-05T11:45:55+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -2476,25 +2466,25 @@ }, { "name": "symfony/filesystem", - "version": "v7.3.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a" + "reference": "7bf9162d7a0dff98d079b72948508fa48018a770" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/e9bcfd7837928ab656276fe00464092cc9e1826a", - "reference": "e9bcfd7837928ab656276fe00464092cc9e1826a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/7bf9162d7a0dff98d079b72948508fa48018a770", + "reference": "7bf9162d7a0dff98d079b72948508fa48018a770", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^6.4|^7.0" + "symfony/process": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2522,7 +2512,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.3.6" + "source": "https://github.com/symfony/filesystem/tree/v8.0.6" }, "funding": [ { @@ -2542,27 +2532,27 @@ "type": "tidelift" } ], - "time": "2025-11-05T09:52:27+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/finder", - "version": "v7.3.5", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f" + "reference": "441404f09a54de6d1bd6ad219e088cdf4c91f97c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9f696d2f1e340484b4683f7853b273abff94421f", - "reference": "9f696d2f1e340484b4683f7853b273abff94421f", + "url": "https://api.github.com/repos/symfony/finder/zipball/441404f09a54de6d1bd6ad219e088cdf4c91f97c", + "reference": "441404f09a54de6d1bd6ad219e088cdf4c91f97c", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.4" }, "require-dev": { - "symfony/filesystem": "^6.4|^7.0" + "symfony/filesystem": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2590,7 +2580,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.3.5" + "source": "https://github.com/symfony/finder/tree/v8.0.6" }, "funding": [ { @@ -2610,117 +2600,99 @@ "type": "tidelift" } ], - "time": "2025-10-15T18:45:57+00:00" + "time": "2026-01-29T09:41:02+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.3.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "cabfdfa82bc4f75d693a329fe263d96937636b77" + "reference": "86ebd86908edca06e3af5994bc46881575fbe813" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/cabfdfa82bc4f75d693a329fe263d96937636b77", - "reference": "cabfdfa82bc4f75d693a329fe263d96937636b77", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/86ebd86908edca06e3af5994bc46881575fbe813", + "reference": "86ebd86908edca06e3af5994bc46881575fbe813", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", - "php": ">=8.2", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^7.3", - "symfony/dependency-injection": "^7.2", + "php": ">=8.4", + "symfony/cache": "^7.4|^8.0", + "symfony/config": "^7.4.4|^8.0.4", + "symfony/dependency-injection": "^7.4.4|^8.0.4", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^7.3", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/filesystem": "^7.1", - "symfony/finder": "^6.4|^7.0", - "symfony/http-foundation": "^7.3", - "symfony/http-kernel": "^7.2", - "symfony/polyfill-mbstring": "~1.0", - "symfony/routing": "^6.4|^7.0" + "symfony/error-handler": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/filesystem": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php85": "^1.32", + "symfony/routing": "^7.4|^8.0" }, "conflict": { "doctrine/persistence": "<1.3", - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/asset": "<6.4", - "symfony/asset-mapper": "<6.4", - "symfony/clock": "<6.4", - "symfony/console": "<6.4", - "symfony/dom-crawler": "<6.4", - "symfony/dotenv": "<6.4", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", - "symfony/json-streamer": ">=7.4", - "symfony/lock": "<6.4", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/mime": "<6.4", - "symfony/object-mapper": ">=7.4", - "symfony/property-access": "<6.4", - "symfony/property-info": "<6.4", - "symfony/runtime": "<6.4.13|>=7.0,<7.1.6", - "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", - "symfony/security-core": "<6.4", - "symfony/security-csrf": "<7.2", - "symfony/serializer": "<7.2.5", - "symfony/stopwatch": "<6.4", - "symfony/translation": "<7.3", - "symfony/twig-bridge": "<6.4", - "symfony/twig-bundle": "<6.4", - "symfony/validator": "<6.4", - "symfony/web-profiler-bundle": "<6.4", - "symfony/webhook": "<7.2", - "symfony/workflow": "<7.3.0-beta2" + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/console": "<7.4", + "symfony/form": "<7.4", + "symfony/json-streamer": "<7.4", + "symfony/messenger": "<7.4", + "symfony/security-csrf": "<7.4", + "symfony/serializer": "<7.4", + "symfony/translation": "<7.4", + "symfony/webhook": "<7.4", + "symfony/workflow": "<7.4" }, "require-dev": { "doctrine/persistence": "^1.3|^2|^3", "dragonmantank/cron-expression": "^3.1", - "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", "seld/jsonlint": "^1.10", - "symfony/asset": "^6.4|^7.0", - "symfony/asset-mapper": "^6.4|^7.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/dotenv": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/html-sanitizer": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/json-streamer": "7.3.*", - "symfony/lock": "^6.4|^7.0", - "symfony/mailer": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/notifier": "^6.4|^7.0", - "symfony/object-mapper": "^v7.3.0-beta2", - "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/scheduler": "^6.4.4|^7.0.4", - "symfony/security-bundle": "^6.4|^7.0", - "symfony/semaphore": "^6.4|^7.0", - "symfony/serializer": "^7.2.5", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/translation": "^7.3", - "symfony/twig-bundle": "^6.4|^7.0", - "symfony/type-info": "^7.1.8", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/web-link": "^6.4|^7.0", - "symfony/webhook": "^7.2", - "symfony/workflow": "^7.3", - "symfony/yaml": "^6.4|^7.0", - "twig/twig": "^3.12" + "symfony/asset": "^7.4|^8.0", + "symfony/asset-mapper": "^7.4|^8.0", + "symfony/browser-kit": "^7.4|^8.0", + "symfony/clock": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/css-selector": "^7.4|^8.0", + "symfony/dom-crawler": "^7.4|^8.0", + "symfony/dotenv": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/form": "^7.4|^8.0", + "symfony/html-sanitizer": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/json-streamer": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/mailer": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/notifier": "^7.4|^8.0", + "symfony/object-mapper": "^7.4|^8.0", + "symfony/polyfill-intl-icu": "^1.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/rate-limiter": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0", + "symfony/scheduler": "^7.4|^8.0", + "symfony/security-bundle": "^7.4|^8.0", + "symfony/semaphore": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/string": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/twig-bundle": "^7.4|^8.0", + "symfony/type-info": "^7.4.1|^8.0.1", + "symfony/uid": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/web-link": "^7.4|^8.0", + "symfony/webhook": "^7.4|^8.0", + "symfony/workflow": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "symfony-bundle", "autoload": { @@ -2748,7 +2720,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/v7.3.6" + "source": "https://github.com/symfony/framework-bundle/tree/v8.0.6" }, "funding": [ { @@ -2768,42 +2740,39 @@ "type": "tidelift" } ], - "time": "2025-10-30T09:42:24+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.3.7", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4" + "reference": "7745ff1aad45d855fe25b08969269ef83b1ad8bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/db488a62f98f7a81d5746f05eea63a74e55bb7c4", - "reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7745ff1aad45d855fe25b08969269ef83b1ad8bc", + "reference": "7745ff1aad45d855fe25b08969269ef83b1ad8bc", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3.0", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php83": "^1.27" + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.1" }, "conflict": { - "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4.12|>=7.0,<7.1.5" + "doctrine/dbal": "<4.3" }, "require-dev": { - "doctrine/dbal": "^3.6|^4", + "doctrine/dbal": "^4.3", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4.12|^7.1.5", - "symfony/clock": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0" + "symfony/cache": "^7.4|^8.0", + "symfony/clock": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/rate-limiter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -2831,7 +2800,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.3.7" + "source": "https://github.com/symfony/http-foundation/tree/v8.0.6" }, "funding": [ { @@ -2851,77 +2820,63 @@ "type": "tidelift" } ], - "time": "2025-11-08T16:41:12+00:00" + "time": "2026-02-21T16:28:39+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.3.7", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce" + "reference": "b567e571e74b5774b3d3cb4d35bdafa5f37e51a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/10b8e9b748ea95fa4539c208e2487c435d3c87ce", - "reference": "10b8e9b748ea95fa4539c208e2487c435d3c87ce", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/b567e571e74b5774b3d3cb4d35bdafa5f37e51a9", + "reference": "b567e571e74b5774b3d3cb4d35bdafa5f37e51a9", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^7.3", - "symfony/http-foundation": "^7.3", + "symfony/error-handler": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "symfony/browser-kit": "<6.4", - "symfony/cache": "<6.4", - "symfony/config": "<6.4", - "symfony/console": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<6.4", - "symfony/form": "<6.4", - "symfony/http-client": "<6.4", + "symfony/flex": "<2.10", "symfony/http-client-contracts": "<2.5", - "symfony/mailer": "<6.4", - "symfony/messenger": "<6.4", - "symfony/translation": "<6.4", "symfony/translation-contracts": "<2.5", - "symfony/twig-bridge": "<6.4", - "symfony/validator": "<6.4", - "symfony/var-dumper": "<6.4", - "twig/twig": "<3.12" + "twig/twig": "<3.21" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/clock": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/css-selector": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/dom-crawler": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", + "symfony/browser-kit": "^7.4|^8.0", + "symfony/clock": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/css-selector": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/dom-crawler": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^7.1", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^7.1", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/translation": "^6.4|^7.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/stopwatch": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", - "twig/twig": "^3.12" + "symfony/uid": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0", + "symfony/var-exporter": "^7.4|^8.0", + "twig/twig": "^3.21" }, "type": "library", "autoload": { @@ -2949,7 +2904,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/v7.3.7" + "source": "https://github.com/symfony/http-kernel/tree/v8.0.6" }, "funding": [ { @@ -2969,52 +2924,49 @@ "type": "tidelift" } ], - "time": "2025-11-12T11:38:40+00:00" + "time": "2026-02-26T08:36:42+00:00" }, { "name": "symfony/messenger", - "version": "v7.3.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "58a7efa3bebadbe4cdd8f7577c5856f0e3ea3978" + "reference": "4be925bf0155d6435d2cdfa63d5ffd277c44ac10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/58a7efa3bebadbe4cdd8f7577c5856f0e3ea3978", - "reference": "58a7efa3bebadbe4cdd8f7577c5856f0e3ea3978", + "url": "https://api.github.com/repos/symfony/messenger/zipball/4be925bf0155d6435d2cdfa63d5ffd277c44ac10", + "reference": "4be925bf0155d6435d2cdfa63d5ffd277c44ac10", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/log": "^1|^2|^3", - "symfony/clock": "^6.4|^7.0", - "symfony/deprecation-contracts": "^2.5|^3" + "symfony/clock": "^7.4|^8.0" }, "conflict": { - "symfony/console": "<7.2", - "symfony/event-dispatcher": "<6.4", + "symfony/console": "<7.4", "symfony/event-dispatcher-contracts": "<2.5", - "symfony/framework-bundle": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/lock": "<6.4", - "symfony/serializer": "<6.4" + "symfony/lock": "<7.4", + "symfony/serializer": "<7.4.4|>=8.0,<8.0.4" }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/console": "^7.2", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/routing": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/lock": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/rate-limiter": "^7.4|^8.0", + "symfony/routing": "^7.4|^8.0", + "symfony/serializer": "^7.4.4|^8.0.4", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0" + "symfony/stopwatch": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3042,7 +2994,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v7.3.6" + "source": "https://github.com/symfony/messenger/tree/v8.0.6" }, "funding": [ { @@ -3062,24 +3014,24 @@ "type": "tidelift" } ], - "time": "2025-11-06T11:17:34+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.3.3", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d" + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/0ff2f5c3df08a395232bbc3c2eb7e84912df911d", - "reference": "0ff2f5c3df08a395232bbc3c2eb7e84912df911d", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d2b592535ffa6600c265a3893a7f7fd2bad82dd7", + "reference": "d2b592535ffa6600c265a3893a7f7fd2bad82dd7", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -3113,7 +3065,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.3.3" + "source": "https://github.com/symfony/options-resolver/tree/v8.0.0" }, "funding": [ { @@ -3133,7 +3085,7 @@ "type": "tidelift" } ], - "time": "2025-08-05T10:16:07+00:00" + "time": "2025-11-12T15:55:31+00:00" }, { "name": "symfony/polyfill-ctype", @@ -3555,17 +3507,17 @@ "time": "2025-01-02T08:10:11+00:00" }, { - "name": "symfony/polyfill-php83", + "name": "symfony/polyfill-php85", "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", + "reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91", "shasum": "" }, "require": { @@ -3583,7 +3535,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" + "Symfony\\Polyfill\\Php85\\": "" }, "classmap": [ "Resources/stubs" @@ -3603,7 +3555,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -3612,7 +3564,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0" }, "funding": [ { @@ -3632,41 +3584,37 @@ "type": "tidelift" } ], - "time": "2025-07-08T02:45:35+00:00" + "time": "2025-06-23T16:12:55+00:00" }, { - "name": "symfony/polyfill-php84", - "version": "v1.33.0", + "name": "symfony/property-access", + "version": "v8.0.4", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + "url": "https://github.com/symfony/property-access.git", + "reference": "a35a5ec85b605d0d1a9fd802cb44d87682c746fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "url": "https://api.github.com/repos/symfony/property-access/zipball/a35a5ec85b605d0d1a9fd802cb44d87682c746fd", + "reference": "a35a5ec85b605d0d1a9fd802cb44d87682c746fd", "shasum": "" }, "require": { - "php": ">=7.2" + "php": ">=8.4", + "symfony/property-info": "^7.4.4|^8.0.4" }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } + "require-dev": { + "symfony/cache": "^7.4|^8.0", + "symfony/var-exporter": "^7.4|^8.0" }, + "type": "library", "autoload": { - "files": [ - "bootstrap.php" - ], "psr-4": { - "Symfony\\Polyfill\\Php84\\": "" + "Symfony\\Component\\PropertyAccess\\": "" }, - "classmap": [ - "Resources/stubs" + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3675,24 +3623,29 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "description": "Provides functions to read and write from/to an object or array using a simple string notation", "homepage": "https://symfony.com", "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" + "access", + "array", + "extraction", + "index", + "injection", + "object", + "property", + "property-path", + "reflection" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + "source": "https://github.com/symfony/property-access/tree/v8.0.4" }, "funding": [ { @@ -3712,41 +3665,37 @@ "type": "tidelift" } ], - "time": "2025-06-24T13:30:11+00:00" + "time": "2026-01-05T09:27:50+00:00" }, { "name": "symfony/property-info", - "version": "v7.3.5", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "0b346ed259dc5da43535caf243005fe7d4b0f051" + "reference": "97524d06a66ae87c59bf9f137420e843cbe4bea0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/0b346ed259dc5da43535caf243005fe7d4b0f051", - "reference": "0b346ed259dc5da43535caf243005fe7d4b0f051", + "url": "https://api.github.com/repos/symfony/property-info/zipball/97524d06a66ae87c59bf9f137420e843cbe4bea0", + "reference": "97524d06a66ae87c59bf9f137420e843cbe4bea0", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0", - "symfony/type-info": "^7.3.5" + "php": ">=8.4", + "symfony/string": "^7.4|^8.0", + "symfony/type-info": "^7.4.4|^8.0.4" }, "conflict": { - "phpdocumentor/reflection-docblock": "<5.2", - "phpdocumentor/type-resolver": "<1.5.1", - "symfony/cache": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/serializer": "<6.4" + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1" }, "require-dev": { - "phpdocumentor/reflection-docblock": "^5.2", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", "phpstan/phpdoc-parser": "^1.0|^2.0", - "symfony/cache": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" + "symfony/cache": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3782,7 +3731,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v7.3.5" + "source": "https://github.com/symfony/property-info/tree/v8.0.6" }, "funding": [ { @@ -3802,40 +3751,40 @@ "type": "tidelift" } ], - "time": "2025-10-05T22:12:41+00:00" + "time": "2026-02-13T12:14:15+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.3.0", + "version": "v8.0.4", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f" + "reference": "d6edf266746dd0b8e81e754a79da77b08dc00531" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", - "reference": "03f2f72319e7acaf2a9f6fcbe30ef17eec51594f", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/d6edf266746dd0b8e81e754a79da77b08dc00531", + "reference": "d6edf266746dd0b8e81e754a79da77b08dc00531", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^6.4|^7.0" + "symfony/http-foundation": "^7.4|^8.0" }, "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-kernel": "<6.4" + "php-http/discovery": "<1.15" }, "require-dev": { "nyholm/psr7": "^1.1", "php-http/discovery": "^1.15", "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0" + "symfony/browser-kit": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/event-dispatcher": "^7.4|^8.0", + "symfony/framework-bundle": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/runtime": "^7.4|^8.0" }, "type": "symfony-bridge", "autoload": { @@ -3869,7 +3818,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.3.0" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v8.0.4" }, "funding": [ { @@ -3880,43 +3829,42 @@ "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": "2024-09-26T08:57:56+00:00" + "time": "2026-01-03T23:40:55+00:00" }, { "name": "symfony/routing", - "version": "v7.3.6", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "c97abe725f2a1a858deca629a6488c8fc20c3091" + "reference": "053c40fd46e1d19c5c5a94cada93ce6c3facdd55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/c97abe725f2a1a858deca629a6488c8fc20c3091", - "reference": "c97abe725f2a1a858deca629a6488c8fc20c3091", + "url": "https://api.github.com/repos/symfony/routing/zipball/053c40fd46e1d19c5c5a94cada93ce6c3facdd55", + "reference": "053c40fd46e1d19c5c5a94cada93ce6c3facdd55", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.4", "symfony/deprecation-contracts": "^2.5|^3" }, - "conflict": { - "symfony/config": "<6.4", - "symfony/dependency-injection": "<6.4", - "symfony/yaml": "<6.4" - }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/config": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -3950,7 +3898,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.3.6" + "source": "https://github.com/symfony/routing/tree/v8.0.6" }, "funding": [ { @@ -3970,62 +3918,56 @@ "type": "tidelift" } ], - "time": "2025-11-05T07:57:47+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/serializer", - "version": "v7.3.5", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "ba2e50a5f2870c93f0f47ca1a4e56e4bbe274035" + "reference": "b923bbb92f84213a927db6ad43576366b7b9ec2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/ba2e50a5f2870c93f0f47ca1a4e56e4bbe274035", - "reference": "ba2e50a5f2870c93f0f47ca1a4e56e4bbe274035", + "url": "https://api.github.com/repos/symfony/serializer/zipball/b923bbb92f84213a927db6ad43576366b7b9ec2a", + "reference": "b923bbb92f84213a927db6ad43576366b7b9ec2a", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-php84": "^1.30" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.2.2", - "phpdocumentor/type-resolver": "<1.4.0", - "symfony/dependency-injection": "<6.4", - "symfony/property-access": "<6.4", - "symfony/property-info": "<6.4", - "symfony/uid": "<6.4", - "symfony/validator": "<6.4", - "symfony/yaml": "<6.4" + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1", + "symfony/property-info": "<7.4", + "symfony/type-info": "<7.4" }, "require-dev": { - "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", "phpstan/phpdoc-parser": "^1.0|^2.0", "seld/jsonlint": "^1.10", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^7.2", - "symfony/error-handler": "^6.4|^7.0", - "symfony/filesystem": "^6.4|^7.0", - "symfony/form": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", + "symfony/cache": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/error-handler": "^7.4|^8.0", + "symfony/filesystem": "^7.4|^8.0", + "symfony/form": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/property-info": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/type-info": "^7.1.8", - "symfony/uid": "^6.4|^7.0", - "symfony/validator": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symfony/var-exporter": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0" + "symfony/type-info": "^7.4|^8.0", + "symfony/uid": "^7.4|^8.0", + "symfony/validator": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0", + "symfony/var-exporter": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4053,7 +3995,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v7.3.5" + "source": "https://github.com/symfony/serializer/tree/v8.0.6" }, "funding": [ { @@ -4073,7 +4015,7 @@ "type": "tidelift" } ], - "time": "2025-10-08T11:26:21+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/service-contracts", @@ -4164,34 +4106,34 @@ }, { "name": "symfony/string", - "version": "v7.3.4", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f96476035142921000338bad71e5247fbc138872" + "reference": "6c9e1108041b5dce21a9a4984b531c4923aa9ec4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f96476035142921000338bad71e5247fbc138872", - "reference": "f96476035142921000338bad71e5247fbc138872", + "url": "https://api.github.com/repos/symfony/string/zipball/6c9e1108041b5dce21a9a4984b531c4923aa9ec4", + "reference": "6c9e1108041b5dce21a9a4984b531c4923aa9ec4", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-intl-grapheme": "^1.33", + "symfony/polyfill-intl-normalizer": "^1.0", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/emoji": "^7.1", - "symfony/http-client": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", + "symfony/emoji": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.4|^7.0" + "symfony/var-exporter": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4230,7 +4172,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.4" + "source": "https://github.com/symfony/string/tree/v8.0.6" }, "funding": [ { @@ -4250,7 +4192,7 @@ "type": "tidelift" } ], - "time": "2025-09-11T14:36:48+00:00" + "time": "2026-02-09T10:14:57+00:00" }, { "name": "symfony/translation-contracts", @@ -4336,22 +4278,21 @@ }, { "name": "symfony/type-info", - "version": "v7.3.5", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/type-info.git", - "reference": "8b36f41421160db56914f897b57eaa6a830758b3" + "reference": "785992c06d07306f963ded3439036f5da9b292fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/type-info/zipball/8b36f41421160db56914f897b57eaa6a830758b3", - "reference": "8b36f41421160db56914f897b57eaa6a830758b3", + "url": "https://api.github.com/repos/symfony/type-info/zipball/785992c06d07306f963ded3439036f5da9b292fe", + "reference": "785992c06d07306f963ded3439036f5da9b292fe", "shasum": "" }, "require": { - "php": ">=8.2", - "psr/container": "^1.1|^2.0", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.4", + "psr/container": "^1.1|^2.0" }, "conflict": { "phpstan/phpdoc-parser": "<1.30" @@ -4395,7 +4336,7 @@ "type" ], "support": { - "source": "https://github.com/symfony/type-info/tree/v7.3.5" + "source": "https://github.com/symfony/type-info/tree/v8.0.6" }, "funding": [ { @@ -4415,60 +4356,52 @@ "type": "tidelift" } ], - "time": "2025-10-16T12:30:12+00:00" + "time": "2026-02-20T07:51:53+00:00" }, { "name": "symfony/validator", - "version": "v7.3.7", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "8290a095497c3fe5046db21888d1f75b54ddf39d" + "reference": "64bcfc222dd26443c6c68d442a1e65397c440c78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/8290a095497c3fe5046db21888d1f75b54ddf39d", - "reference": "8290a095497c3fe5046db21888d1f75b54ddf39d", + "url": "https://api.github.com/repos/symfony/validator/zipball/64bcfc222dd26443c6c68d442a1e65397c440c78", + "reference": "64bcfc222dd26443c6c68d442a1e65397c440c78", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php83": "^1.27", + "php": ">=8.4", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.0", "symfony/translation-contracts": "^2.5|^3" }, "conflict": { "doctrine/lexer": "<1.1", - "symfony/dependency-injection": "<6.4", - "symfony/doctrine-bridge": "<7.0", - "symfony/expression-language": "<6.4", - "symfony/http-kernel": "<6.4", - "symfony/intl": "<6.4", - "symfony/property-info": "<6.4", - "symfony/translation": "<6.4.3|>=7.0,<7.0.3", - "symfony/yaml": "<6.4" + "symfony/doctrine-bridge": "<7.4" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3|^4", - "symfony/cache": "^6.4|^7.0", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/expression-language": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/http-client": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/intl": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", - "symfony/property-access": "^6.4|^7.0", - "symfony/property-info": "^6.4|^7.0", - "symfony/string": "^6.4|^7.0", - "symfony/translation": "^6.4.3|^7.0.3", - "symfony/type-info": "^7.1.8", - "symfony/yaml": "^6.4|^7.0" + "symfony/cache": "^7.4|^8.0", + "symfony/config": "^7.4|^8.0", + "symfony/console": "^7.4|^8.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/expression-language": "^7.4|^8.0", + "symfony/finder": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/http-foundation": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/intl": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/string": "^7.4|^8.0", + "symfony/translation": "^7.4|^8.0", + "symfony/type-info": "^7.4|^8.0", + "symfony/yaml": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4497,7 +4430,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v7.3.7" + "source": "https://github.com/symfony/validator/tree/v8.0.6" }, "funding": [ { @@ -4517,35 +4450,35 @@ "type": "tidelift" } ], - "time": "2025-11-08T16:29:29+00:00" + "time": "2026-02-25T16:59:43+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.3.5", + "version": "v8.0.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d" + "reference": "2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/476c4ae17f43a9a36650c69879dcf5b1e6ae724d", - "reference": "476c4ae17f43a9a36650c69879dcf5b1e6ae724d", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209", + "reference": "2e14f7e0bf5ff02c6e63bd31cb8e4855a13d6209", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=8.4", + "symfony/polyfill-mbstring": "^1.0" }, "conflict": { - "symfony/console": "<6.4" + "symfony/console": "<7.4", + "symfony/error-handler": "<7.4" }, "require-dev": { - "symfony/console": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/uid": "^6.4|^7.0", + "symfony/console": "^7.4|^8.0", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/uid": "^7.4|^8.0", "twig/twig": "^3.12" }, "bin": [ @@ -4584,7 +4517,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.3.5" + "source": "https://github.com/symfony/var-dumper/tree/v8.0.6" }, "funding": [ { @@ -4604,30 +4537,29 @@ "type": "tidelift" } ], - "time": "2025-09-27T09:00:46+00:00" + "time": "2026-02-15T10:53:29+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.3.4", + "version": "v8.0.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "0f020b544a30a7fe8ba972e53ee48a74c0bc87f4" + "reference": "7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/0f020b544a30a7fe8ba972e53ee48a74c0bc87f4", - "reference": "0f020b544a30a7fe8ba972e53ee48a74c0bc87f4", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04", + "reference": "7345f46c251f2eb27c7b3ebdb5bb076b3ffcae04", "shasum": "" }, "require": { - "php": ">=8.2", - "symfony/deprecation-contracts": "^2.5|^3" + "php": ">=8.4" }, "require-dev": { - "symfony/property-access": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0" + "symfony/property-access": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" }, "type": "library", "autoload": { @@ -4665,7 +4597,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.3.4" + "source": "https://github.com/symfony/var-exporter/tree/v8.0.0" }, "funding": [ { @@ -4685,20 +4617,20 @@ "type": "tidelift" } ], - "time": "2025-09-11T10:12:26+00:00" + "time": "2025-11-05T18:53:00+00:00" }, { "name": "symfony/yaml", - "version": "v7.4.1", + "version": "v7.4.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "24dd4de28d2e3988b311751ac49e684d783e2345" + "reference": "58751048de17bae71c5aa0d13cb19d79bca26391" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/24dd4de28d2e3988b311751ac49e684d783e2345", - "reference": "24dd4de28d2e3988b311751ac49e684d783e2345", + "url": "https://api.github.com/repos/symfony/yaml/zipball/58751048de17bae71c5aa0d13cb19d79bca26391", + "reference": "58751048de17bae71c5aa0d13cb19d79bca26391", "shasum": "" }, "require": { @@ -4741,7 +4673,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.4.1" + "source": "https://github.com/symfony/yaml/tree/v7.4.6" }, "funding": [ { @@ -4761,7 +4693,7 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:11:45+00:00" + "time": "2026-02-09T09:33:46+00:00" }, { "name": "webmozart/assert", @@ -4823,16 +4755,16 @@ }, { "name": "zircote/swagger-php", - "version": "5.7.3", + "version": "5.8.2", "source": { "type": "git", "url": "https://github.com/zircote/swagger-php.git", - "reference": "4d0d3086d7c876626167d198cec285e98d3629dc" + "reference": "18ee6592518238a5a6c9905aae4926d5bbc65754" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zircote/swagger-php/zipball/4d0d3086d7c876626167d198cec285e98d3629dc", - "reference": "4d0d3086d7c876626167d198cec285e98d3629dc", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/18ee6592518238a5a6c9905aae4926d5bbc65754", + "reference": "18ee6592518238a5a6c9905aae4926d5bbc65754", "shasum": "" }, "require": { @@ -4842,8 +4774,8 @@ "phpstan/phpdoc-parser": "^2.0", "psr/log": "^1.1 || ^2.0 || ^3.0", "symfony/deprecation-contracts": "^2 || ^3", - "symfony/finder": "^5.0 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + "symfony/finder": "^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.0" }, "conflict": { "symfony/process": ">=6, <6.4.14" @@ -4854,7 +4786,7 @@ "friendsofphp/php-cs-fixer": "^3.62.0", "phpstan/phpstan": "^1.6 || ^2.0", "phpunit/phpunit": "^9.0", - "rector/rector": "^1.0 || ^2.0", + "rector/rector": "^1.0 || ^2.3.1", "vimeo/psalm": "^4.30 || ^5.0" }, "suggest": { @@ -4905,9 +4837,15 @@ ], "support": { "issues": "https://github.com/zircote/swagger-php/issues", - "source": "https://github.com/zircote/swagger-php/tree/5.7.3" + "source": "https://github.com/zircote/swagger-php/tree/5.8.2" }, - "time": "2025-11-17T20:56:13+00:00" + "funding": [ + { + "url": "https://github.com/zircote", + "type": "github" + } + ], + "time": "2026-02-10T20:10:15+00:00" } ], "packages-dev": [ @@ -5408,6 +5346,64 @@ ], "time": "2025-11-28T22:07:42+00:00" }, + { + "name": "nyholm/symfony-bundle-test", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/SymfonyTest/symfony-bundle-test.git", + "reference": "d4bec46243d9b78f303208e4b9cc18c27f921f1a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SymfonyTest/symfony-bundle-test/zipball/d4bec46243d9b78f303208e4b9cc18c27f921f1a", + "reference": "d4bec46243d9b78f303208e4b9cc18c27f921f1a", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.0" + }, + "conflict": { + "phpunit/phpunit": "<=8.5.14" + }, + "require-dev": { + "phpunit/phpunit": "^8.5 || ^9.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Nyholm\\BundleTest\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "keywords": [ + "testing" + ], + "support": { + "issues": "https://github.com/SymfonyTest/symfony-bundle-test/issues", + "source": "https://github.com/SymfonyTest/symfony-bundle-test/tree/3.1.0" + }, + "time": "2025-08-05T14:11:57+00:00" + }, { "name": "phpstan/extension-installer", "version": "1.4.3", @@ -6228,16 +6224,16 @@ }, { "name": "symfony/phpunit-bridge", - "version": "v8.0.0", + "version": "v8.0.3", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "51b2adaf2cdb00cdab11e6b593e37ef76358e161" + "reference": "3c59b07980df5d4ae4a2620287016209802261ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/51b2adaf2cdb00cdab11e6b593e37ef76358e161", - "reference": "51b2adaf2cdb00cdab11e6b593e37ef76358e161", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/3c59b07980df5d4ae4a2620287016209802261ea", + "reference": "3c59b07980df5d4ae4a2620287016209802261ea", "shasum": "" }, "require": { @@ -6289,7 +6285,7 @@ "testing" ], "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v8.0.0" + "source": "https://github.com/symfony/phpunit-bridge/tree/v8.0.3" }, "funding": [ { @@ -6309,7 +6305,7 @@ "type": "tidelift" } ], - "time": "2025-10-29T07:48:08+00:00" + "time": "2025-12-10T13:10:54+00:00" }, { "name": "symfony/polyfill-php81", @@ -6391,18 +6387,98 @@ ], "time": "2024-09-09T11:45:10+00:00" }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.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": "2025-06-24T13:30:11+00:00" + }, { "name": "symfony/process", - "version": "v8.0.0", + "version": "v8.0.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "a0a750500c4ce900d69ba4e9faf16f82c10ee149" + "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/a0a750500c4ce900d69ba4e9faf16f82c10ee149", - "reference": "a0a750500c4ce900d69ba4e9faf16f82c10ee149", + "url": "https://api.github.com/repos/symfony/process/zipball/b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", + "reference": "b5f3aa6762e33fd95efbaa2ec4f4bc9fdd16d674", "shasum": "" }, "require": { @@ -6434,7 +6510,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v8.0.0" + "source": "https://github.com/symfony/process/tree/v8.0.5" }, "funding": [ { @@ -6454,7 +6530,7 @@ "type": "tidelift" } ], - "time": "2025-10-16T16:25:44+00:00" + "time": "2026-01-26T15:08:38+00:00" }, { "name": "symfony/stopwatch", diff --git a/config/controller.php b/config/controller.php index 9b14caf..f7223b3 100644 --- a/config/controller.php +++ b/config/controller.php @@ -4,23 +4,32 @@ use Stixx\OpenApiCommandBundle\Controller\ArgumentResolver\CommandValueResolver; use Stixx\OpenApiCommandBundle\Controller\CommandController; +use Stixx\OpenApiCommandBundle\Responder\ResponderInterface; +use Stixx\OpenApiCommandBundle\Response\StatusResolverInterface; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; use function Symfony\Component\DependencyInjection\Loader\Configurator\param; +use function Symfony\Component\DependencyInjection\Loader\Configurator\service; return static function (ContainerConfigurator $configurator): void { $services = $configurator->services() ->defaults() - ->autowire() - ->autoconfigure(false) ->private(); $services ->set(CommandController::class) + ->public() ->tag('controller.service_arguments') + ->arg('$commandBus', service(MessageBusInterface::class)) + ->arg('$validator', service(ValidatorInterface::class)) + ->arg('$statusResolver', service(StatusResolverInterface::class)) + ->arg('$responder', service(ResponderInterface::class)) ->arg('$validationEnabled', param('stixx_openapi_command.validation.enabled')) ->arg('$validationGroups', param('stixx_openapi_command.validation.groups')); $services ->set(CommandValueResolver::class) + ->arg('$serializer', service('serializer')) ->tag('controller.argument_value_resolver'); }; diff --git a/config/openapi.php b/config/openapi.php index 1c268c3..2369a09 100644 --- a/config/openapi.php +++ b/config/openapi.php @@ -10,13 +10,12 @@ return static function (ContainerConfigurator $configurator): void { $services = $configurator->services() ->defaults() - ->autowire() - ->autoconfigure(false) ->private(); $services ->set(CommandRouteDescriber::class) ->arg('$argumentMetadataFactory', service('argument_metadata_factory')) ->arg('$inlineParameterDescribers', tagged_iterator('nelmio_api_doc.route_argument_describer')) + ->arg('$attributesCache', []) ->tag('nelmio_api_doc.route_describer', ['priority' => -260]); }; diff --git a/config/response.php b/config/response.php index 942288e..aaa210b 100644 --- a/config/response.php +++ b/config/response.php @@ -10,14 +10,12 @@ use Stixx\OpenApiCommandBundle\Response\ResponseStatusResolver; use Stixx\OpenApiCommandBundle\Response\StatusResolverInterface; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; - +use function Symfony\Component\DependencyInjection\Loader\Configurator\service; use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator; return static function (ContainerConfigurator $configurator): void { $services = $configurator->services() ->defaults() - ->autowire() - ->autoconfigure(false) ->private(); $services @@ -25,14 +23,14 @@ ->arg('$responders', tagged_iterator(ResponderInterface::TAG_NAME)); $services->alias(ResponderInterface::class, ResponderChain::class); - $services - ->instanceof(ResponderInterface::class) - ->tag(ResponderInterface::TAG_NAME); - $services->set(ResponseStatusResolver::class); $services->alias(StatusResolverInterface::class, ResponseStatusResolver::class); - $services->set(JsonResponder::class); - $services->set(JsonSerializedResponder::class); - $services->set(NullableResponder::class); + $services->set(JsonResponder::class) + ->tag(ResponderInterface::TAG_NAME); + $services->set(JsonSerializedResponder::class) + ->arg('$serializer', service('serializer')) + ->tag(ResponderInterface::TAG_NAME); + $services->set(NullableResponder::class) + ->tag(ResponderInterface::TAG_NAME); }; diff --git a/config/routing.php b/config/routing.php index 4edf9eb..618aac6 100644 --- a/config/routing.php +++ b/config/routing.php @@ -12,8 +12,6 @@ return static function (ContainerConfigurator $configurator): void { $services = $configurator->services() ->defaults() - ->autowire() - ->autoconfigure(false) ->private(); $services @@ -22,7 +20,9 @@ $services ->set(CommandRouteClassLoader::class) - ->arg('$controllerClasses', param('stixx_openapi_command.controller_classes')); + ->arg('$env', param('kernel.environment')) + ->arg('$controllerClasses', param('stixx_openapi_command.controller_classes')) + ->tag('routing.loader'); $services ->set(AttributeDirectoryLoaderDecorator::class) diff --git a/config/serializer.php b/config/serializer.php index 84212c2..2001a4b 100644 --- a/config/serializer.php +++ b/config/serializer.php @@ -7,6 +7,7 @@ use Stixx\OpenApiCommandBundle\Serializer\Normalizer\ConstraintViolationNormalizer; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use function Symfony\Component\DependencyInjection\Loader\Configurator\param; use function Symfony\Component\DependencyInjection\Loader\Configurator\service; use Symfony\Component\Serializer\Serializer; @@ -14,13 +15,11 @@ return static function (ContainerConfigurator $configurator): void { $services = $configurator->services() ->defaults() - ->autowire() - ->autoconfigure(false) ->private(); $services ->set(ApiProblemNormalizer::class) - ->arg('$debug', '%kernel.debug%') + ->arg('$debug', param('kernel.debug')) ->tag('serializer.normalizer'); $services ->set(ConstraintViolationNormalizer::class) diff --git a/config/subscribers.php b/config/subscribers.php index f2ace9c..6a6e449 100644 --- a/config/subscribers.php +++ b/config/subscribers.php @@ -6,14 +6,14 @@ use Stixx\OpenApiCommandBundle\EventSubscriber\RequestValidatorSubscriber; use Stixx\OpenApiCommandBundle\Exception\DefaultExceptionToApiProblemTransformer; use Stixx\OpenApiCommandBundle\Exception\ExceptionToApiProblemTransformerInterface; +use Stixx\OpenApiCommandBundle\Routing\NelmioAreaRoutesChecker; +use Stixx\OpenApiCommandBundle\Validator\RequestValidatorChain; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; use function Symfony\Component\DependencyInjection\Loader\Configurator\service; return static function (ContainerConfigurator $configurator): void { $services = $configurator->services() ->defaults() - ->autowire() - ->autoconfigure(false) ->private(); $services @@ -24,9 +24,13 @@ $services ->set(ApiExceptionSubscriber::class) - ->arg('$serializer', service('stixx_openapi_command.problem_serializer')) + ->arg('$nelmioAreaRoutesChecker', service(NelmioAreaRoutesChecker::class)) + ->arg('$normalizer', service('stixx_openapi_command.problem_serializer')) + ->arg('$exceptionTransformer', service(ExceptionToApiProblemTransformerInterface::class)) ->tag('kernel.event_subscriber'); $services ->set(RequestValidatorSubscriber::class) + ->arg('$requestValidatorChain', service(RequestValidatorChain::class)) + ->arg('$nelmioAreaRoutes', service(NelmioAreaRoutesChecker::class)) ->tag('kernel.event_subscriber'); }; diff --git a/config/validators.php b/config/validators.php index 6f6893d..7d9fa0b 100644 --- a/config/validators.php +++ b/config/validators.php @@ -12,8 +12,6 @@ return static function (ContainerConfigurator $configurator): void { $services = $configurator->services() ->defaults() - ->autowire() - ->autoconfigure(false) ->private(); $services @@ -21,11 +19,8 @@ ->arg('$validators', tagged_iterator(StixxValidatorInterface::TAG_NAME)); $services->alias(StixxValidatorInterface::class, RequestValidatorChain::class); - $services - ->instanceof(StixxValidatorInterface::class) - ->tag(StixxValidatorInterface::TAG_NAME); - $services ->set(RequestValidator::class) - ->arg('$apiDocGenerator', service('nelmio_api_doc.generator.default')); + ->arg('$apiDocGenerator', service('nelmio_api_doc.generator.default')) + ->tag(StixxValidatorInterface::TAG_NAME); }; diff --git a/phpunit.xml b/phpunit.xml index ab9ec47..6859fec 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -10,6 +10,7 @@ > + @@ -21,9 +22,9 @@ - + ./src/ - + diff --git a/src/Controller/ArgumentResolver/CommandValueResolver.php b/src/Controller/ArgumentResolver/CommandValueResolver.php index 9e21823..0adaa6f 100644 --- a/src/Controller/ArgumentResolver/CommandValueResolver.php +++ b/src/Controller/ArgumentResolver/CommandValueResolver.php @@ -113,8 +113,7 @@ private function extractScalarsFromRouteAndQuery(Request $request): array $routeData = array_filter( $attributes, static function ($value, $key): bool { - return is_string($key) - && $key !== '' + return $key !== '' && $key[0] !== '_' && (is_scalar($value) || $value === null); }, diff --git a/src/DependencyInjection/StixxOpenApiCommandExtension.php b/src/DependencyInjection/StixxOpenApiCommandExtension.php index 5451bd8..50499aa 100644 --- a/src/DependencyInjection/StixxOpenApiCommandExtension.php +++ b/src/DependencyInjection/StixxOpenApiCommandExtension.php @@ -42,7 +42,7 @@ public function load(array $configs, ContainerBuilder $container): void ->addTag(ValidatorInterface::TAG_NAME); $loader = new PhpFileLoader($container, new FileLocator(__DIR__.'/../../config')); - $this->registerCommonConfiguration($loader); + $this->registerCommonConfiguration($loader, $container); } public function getAlias(): string @@ -50,7 +50,7 @@ public function getAlias(): string return Configuration::BUNDLE_ALIAS; } - private function registerCommonConfiguration(PhpFileLoader $loader): void + private function registerCommonConfiguration(PhpFileLoader $loader, ContainerBuilder $container): void { $loader->load('controller.php'); $loader->load('response.php'); @@ -59,5 +59,7 @@ private function registerCommonConfiguration(PhpFileLoader $loader): void $loader->load('validators.php'); $loader->load('openapi.php'); $loader->load('serializer.php'); + + $container->setParameter('stixx_openapi_command.controller_classes', []); } } diff --git a/src/EventSubscriber/ApiExceptionSubscriber.php b/src/EventSubscriber/ApiExceptionSubscriber.php index 5f18259..a50db30 100644 --- a/src/EventSubscriber/ApiExceptionSubscriber.php +++ b/src/EventSubscriber/ApiExceptionSubscriber.php @@ -35,7 +35,7 @@ public function __construct( public static function getSubscribedEvents(): array { return [ - KernelEvents::EXCEPTION => ['onKernelException', 0], + KernelEvents::EXCEPTION => ['onKernelException', 256], ]; } diff --git a/src/Response/ResponseStatusResolver.php b/src/Response/ResponseStatusResolver.php index 2c13c6f..24ff927 100644 --- a/src/Response/ResponseStatusResolver.php +++ b/src/Response/ResponseStatusResolver.php @@ -75,6 +75,9 @@ private function findOperationAttributeForMethod(object $command, string $method private function first2xxFromOperation(Operation $operation): ?int { $responses = $operation->responses; + if (!is_iterable($responses)) { + return null; + } foreach ($responses as $response) { $code = $response->response; diff --git a/tests/Functional/.gitignore b/tests/Functional/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/tests/Functional/AbstractKernelTestCase.php b/tests/Functional/AbstractKernelTestCase.php new file mode 100644 index 0000000..039ff97 --- /dev/null +++ b/tests/Functional/AbstractKernelTestCase.php @@ -0,0 +1,45 @@ +boot(); + + return $kernel; + } +} diff --git a/tests/Functional/App/Command/CreateBookCommand.php b/tests/Functional/App/Command/CreateBookCommand.php new file mode 100644 index 0000000..38a174c --- /dev/null +++ b/tests/Functional/App/Command/CreateBookCommand.php @@ -0,0 +1,38 @@ +title, $command->author); + } +} diff --git a/tests/Functional/App/Handler/DeleteBookHandler.php b/tests/Functional/App/Handler/DeleteBookHandler.php new file mode 100644 index 0000000..16048a9 --- /dev/null +++ b/tests/Functional/App/Handler/DeleteBookHandler.php @@ -0,0 +1,24 @@ +id, $command->title, $command->author); + } +} diff --git a/tests/Functional/App/Kernel.php b/tests/Functional/App/Kernel.php new file mode 100644 index 0000000..0e3e6b4 --- /dev/null +++ b/tests/Functional/App/Kernel.php @@ -0,0 +1,53 @@ +addTestBundle(FrameworkBundle::class); + $this->addTestBundle(NelmioApiDocBundle::class); + $this->addTestBundle(StixxOpenApiCommandBundle::class); + $this->addTestConfig(__DIR__.'/../Resources/config/default.php'); + } + + public function getProjectDir(): string + { + return __DIR__.'/../'; + } + + /** + * @param RoutingConfigurator $routes + */ + protected function configureRoutes($routes): void + { + parent::configureRoutes($routes); + + if ($routes instanceof RoutingConfigurator) { + $routes->import(CreateBookCommand::class, 'attribute'); + $routes->import(UpdateBookCommand::class, 'attribute'); + $routes->import(DeleteBookCommand::class, 'attribute'); + } + } +} diff --git a/tests/Functional/App/Model/BookRequest.php b/tests/Functional/App/Model/BookRequest.php new file mode 100644 index 0000000..2772f7c --- /dev/null +++ b/tests/Functional/App/Model/BookRequest.php @@ -0,0 +1,29 @@ +bootKernel(); + $container = self::getContainer(); + + // Assert + $this->assertTrue($container->hasParameter('stixx_openapi_command.validation.enabled')); + $this->assertTrue($container->hasParameter('stixx_openapi_command.validation.groups')); + + // Controllers & Resolvers + $this->assertTrue($container->has(CommandController::class)); + $this->assertTrue($container->has(CommandValueResolver::class)); + + // Subscribers + $this->assertTrue($container->has(ApiExceptionSubscriber::class)); + $this->assertTrue($container->has(RequestValidatorSubscriber::class)); + + // Exceptions + $this->assertTrue($container->has(DefaultExceptionToApiProblemTransformer::class)); + $this->assertTrue($container->has(ExceptionToApiProblemTransformerInterface::class)); + + // Responders + $this->assertTrue($container->has(ResponderChain::class)); + $this->assertTrue($container->has(ResponderInterface::class)); + $this->assertTrue($container->has(JsonResponder::class)); + $this->assertTrue($container->has(JsonSerializedResponder::class)); + $this->assertTrue($container->has(NullableResponder::class)); + + // Response Status + $this->assertTrue($container->has(ResponseStatusResolver::class)); + $this->assertTrue($container->has(StatusResolverInterface::class)); + + // OpenAPI + $this->assertTrue($container->has(CommandRouteDescriber::class)); + + // Routing + $this->assertTrue($container->has(NelmioAreaRoutesChecker::class)); + $this->assertTrue($container->has(CommandRouteClassLoader::class)); + $this->assertTrue($container->has(AttributeDirectoryLoaderDecorator::class)); + + // Validators + $this->assertTrue($container->has(RequestValidatorChain::class)); + $this->assertTrue($container->has(StixxValidatorInterface::class)); + $this->assertTrue($container->has(RequestValidator::class)); + + // Serializer + $this->assertTrue($container->has(ApiProblemNormalizer::class)); + $this->assertTrue($container->has(ConstraintViolationNormalizer::class)); + $this->assertTrue($container->has(ConstraintViolationListNormalizer::class)); + $this->assertTrue($container->has('stixx_openapi_command.problem_serializer')); + $this->assertInstanceOf(Serializer::class, $container->get('stixx_openapi_command.problem_serializer')); + } + + #[WithoutErrorHandler] + public function testBundleWithCustomConfiguration(): void + { + // Arrange + $kernel = $this->createKernelWithConfig(static function (Kernel $kernel): void { + $kernel->addTestConfig(__DIR__.'/Resources/config/custom.php'); + }); + $container = $kernel->getContainer(); + + // Act + $enabled = $container->getParameter('stixx_openapi_command.validation.enabled'); + $groups = $container->getParameter('stixx_openapi_command.validation.groups'); + + // Assert + $this->assertFalse($enabled); + $this->assertSame(['Custom'], $groups); + } +} diff --git a/tests/Functional/OpenApiSchemaTest.php b/tests/Functional/OpenApiSchemaTest.php new file mode 100644 index 0000000..547b884 --- /dev/null +++ b/tests/Functional/OpenApiSchemaTest.php @@ -0,0 +1,37 @@ +get('nelmio_api_doc.generator.default'); + + // Act + $openApi = $generator->generate(); + $json = $openApi->toJson(); + + // Assert + $this->assertJsonStringEqualsJsonFile(__DIR__.'/Resources/specifications/openapi.json', $json); + } +} diff --git a/tests/Functional/Resources/config/custom.php b/tests/Functional/Resources/config/custom.php new file mode 100644 index 0000000..6ff69b1 --- /dev/null +++ b/tests/Functional/Resources/config/custom.php @@ -0,0 +1,51 @@ +extension('framework', [ + 'test' => true, + 'messenger' => [ + 'enabled' => true, + ], + 'serializer' => [ + 'enabled' => true, + ], + 'validation' => [ + 'enabled' => true, + ], + 'http_method_override' => false, + 'handle_all_throwables' => true, + 'php_errors' => [ + 'log' => true, + ], + ]); + + $container->extension('nelmio_api_doc', [ + 'areas' => [ + 'default' => [ + 'path_patterns' => ['^/api'], + ], + ], + ]); + + $container->extension('stixx_openapi_command', [ + 'validation' => [ + 'enabled' => false, + 'groups' => ['Custom'], + ], + ]); + + $container->parameters()->set('validator.translation_domain', 'validators'); +}; diff --git a/tests/Functional/Resources/config/default.php b/tests/Functional/Resources/config/default.php new file mode 100644 index 0000000..676a74d --- /dev/null +++ b/tests/Functional/Resources/config/default.php @@ -0,0 +1,49 @@ +extension('framework', [ + 'test' => true, + 'messenger' => [ + 'enabled' => true, + ], + 'serializer' => [ + 'enabled' => true, + ], + 'validation' => [ + 'enabled' => true, + ], + 'http_method_override' => false, + 'php_errors' => [ + 'log' => false, + ], + ]); + + $container->extension('nelmio_api_doc', [ + 'areas' => [ + 'default' => [ + 'path_patterns' => ['^/api'], + ], + ], + ]); + + $container->extension('stixx_openapi_command', [ + 'validation' => [ + 'enabled' => true, + ], + ]); + + $container->parameters()->set('validator.translation_domain', 'validators'); +}; diff --git a/tests/Functional/Resources/config/scenario.php b/tests/Functional/Resources/config/scenario.php new file mode 100644 index 0000000..3f02503 --- /dev/null +++ b/tests/Functional/Resources/config/scenario.php @@ -0,0 +1,72 @@ +services() + ->defaults() + ->public(); + + $services + ->set(CreateBookHandler::class) + ->tag('messenger.message_handler'); + + $services + ->set(UpdateBookHandler::class) + ->tag('messenger.message_handler'); + + $services + ->set(DeleteBookHandler::class) + ->tag('messenger.message_handler'); + + $services->set(PhpDocExtractor::class); + $services->set(ReflectionExtractor::class); + $services->set(PropertyInfoExtractor::class) + ->arg('$listExtractors', [service(ReflectionExtractor::class)]) + ->arg('$typeExtractors', [service(PhpDocExtractor::class), service(ReflectionExtractor::class)]) + ->arg('$accessExtractors', [service(ReflectionExtractor::class)]) + ->arg('$initializableExtractors', [service(ReflectionExtractor::class)]); + + $services->set(ObjectNormalizer::class) + ->arg('$propertyTypeExtractor', service(PropertyInfoExtractor::class)) + ->tag('serializer.normalizer'); + + $services->set(ArrayDenormalizer::class) + ->tag('serializer.normalizer'); + + $services->set(JsonEncoder::class) + ->tag('serializer.encoder'); + + $services->set('test.serializer', Serializer::class) + ->arg('$normalizers', [ + service(ArrayDenormalizer::class), + service(ObjectNormalizer::class), + ]) + ->arg('$encoders', [ + service(JsonEncoder::class), + ]); + + $services->alias('serializer', 'test.serializer'); +}; diff --git a/tests/Functional/Resources/specifications/openapi.json b/tests/Functional/Resources/specifications/openapi.json new file mode 100644 index 0000000..5729d83 --- /dev/null +++ b/tests/Functional/Resources/specifications/openapi.json @@ -0,0 +1,144 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "", + "version": "0.0.0" + }, + "paths": { + "/api/books": { + "post": { + "summary": "Create a book", + "operationId": "post_command_createbookcommand", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookRequest" + } + } + } + }, + "responses": { + "201": { + "description": "Book created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookResource" + } + } + } + } + } + } + }, + "/api/books/{id}": { + "put": { + "summary": "Update a book", + "operationId": "put_command_updatebookcommand", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Book updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookResource" + } + } + } + } + } + }, + "delete": { + "summary": "Delete a book", + "operationId": "delete_command_deletebookcommand", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "Book deleted" + } + } + } + } + }, + "components": { + "schemas": { + "BookRequest": { + "title": "BookRequest", + "description": "Request payload for a book", + "required": [ + "title" + ], + "properties": { + "title": { + "description": "The title of the book", + "type": "string" + }, + "author": { + "description": "The author of the book", + "type": "string", + "maxLength": 100, + "minLength": 1, + "nullable": true + } + }, + "type": "object" + }, + "BookResource": { + "title": "BookResource", + "description": "A book resource", + "required": [ + "id", + "title" + ], + "properties": { + "id": { + "description": "The unique identifier of the book", + "type": "string" + }, + "title": { + "description": "The title of the book", + "type": "string" + }, + "author": { + "description": "The author of the book", + "type": "string", + "default": null, + "nullable": true + } + }, + "type": "object" + } + } + } +} \ No newline at end of file diff --git a/tests/Functional/ScenarioTest.php b/tests/Functional/ScenarioTest.php new file mode 100644 index 0000000..fee0b59 --- /dev/null +++ b/tests/Functional/ScenarioTest.php @@ -0,0 +1,171 @@ +createKernelWithConfig(static function (Kernel $kernel): void { + $kernel->addTestConfig(__DIR__.'/Resources/config/scenario.php'); + }); + + $payload = [ + 'title' => 'Domain-Driven Design', + 'author' => 'Eric Evans', + ]; + + $request = Request::create( + uri: '/api/books', + method: 'POST', + content: json_encode($payload, JSON_THROW_ON_ERROR) + ); + $request->headers->set('Content-Type', 'application/json'); + + // Act + $response = $kernel->handle($request); + + // Assert + self::assertSame(201, $response->getStatusCode()); + self::assertSame('application/json', $response->headers->get('Content-Type')); + $data = json_decode($response->getContent() ?: 'null', true, 512, JSON_THROW_ON_ERROR); + self::assertIsArray($data); + self::assertSame('Domain-Driven Design', $data['title'] ?? null); + self::assertSame('Eric Evans', $data['author'] ?? null); + self::assertArrayHasKey('id', $data); + } + + #[WithoutErrorHandler] + public function testUpdateBookSuccess(): void + { + // Arrange + $kernel = $this->createKernelWithConfig(static function (Kernel $kernel): void { + $kernel->addTestConfig(__DIR__.'/Resources/config/scenario.php'); + }); + + $payload = [ + 'title' => 'Domain-Driven Design - Revised', + 'author' => 'Eric Evans', + ]; + + $request = Request::create( + uri: '/api/books/1', + method: 'PUT', + content: json_encode($payload, JSON_THROW_ON_ERROR) + ); + $request->headers->set('Content-Type', 'application/json'); + + // Act + $response = $kernel->handle($request); + + // Assert + self::assertSame(200, $response->getStatusCode()); + self::assertSame('application/json', $response->headers->get('Content-Type')); + $data = json_decode($response->getContent() ?: 'null', true, 512, JSON_THROW_ON_ERROR); + self::assertIsArray($data); + self::assertSame('1', $data['id'] ?? null); + self::assertSame('Domain-Driven Design - Revised', $data['title'] ?? null); + } + + #[WithoutErrorHandler] + public function testDeleteBookSuccess(): void + { + // Arrange + $kernel = $this->createKernelWithConfig(static function (Kernel $kernel): void { + $kernel->addTestConfig(__DIR__.'/Resources/config/scenario.php'); + }); + + $request = Request::create( + uri: '/api/books/1', + method: 'DELETE' + ); + + // Act + $response = $kernel->handle($request); + + // Assert + self::assertSame(204, $response->getStatusCode()); + self::assertEmpty($response->getContent()); + } + + #[WithoutErrorHandler] + public function testCreateBookValidationError(): void + { + // Arrange + $kernel = $this->createKernelWithConfig(static function (Kernel $kernel): void { + $kernel->addTestConfig(__DIR__.'/Resources/config/scenario.php'); + }); + + $payload = [ + 'title' => '', // NotBlank + ]; + + $request = Request::create( + uri: '/api/books', + method: 'POST', + content: json_encode($payload, JSON_THROW_ON_ERROR) + ); + $request->headers->set('Content-Type', 'application/json'); + + // Act + $response = $kernel->handle($request); + + // Assert + self::assertSame(400, $response->getStatusCode()); + self::assertSame('application/problem+json', $response->headers->get('Content-Type')); + $data = json_decode($response->getContent() ?: 'null', true, 512, JSON_THROW_ON_ERROR); + self::assertIsArray($data); + self::assertSame(400, $data['status'] ?? null); + self::assertSame('Validation failed', $data['detail'] ?? null); + self::assertArrayHasKey('violations', $data); + } + + #[WithoutErrorHandler] + public function testUpdateBookValidationError(): void + { + // Arrange + $kernel = $this->createKernelWithConfig(static function (Kernel $kernel): void { + $kernel->addTestConfig(__DIR__.'/Resources/config/scenario.php'); + }); + + $payload = [ + 'title' => '', // NotBlank + ]; + + $request = Request::create( + uri: '/api/books/1', + method: 'PUT', + content: json_encode($payload, JSON_THROW_ON_ERROR) + ); + $request->headers->set('Content-Type', 'application/json'); + + // Act + $response = $kernel->handle($request); + + // Assert + self::assertSame(400, $response->getStatusCode()); + self::assertSame('application/problem+json', $response->headers->get('Content-Type')); + $data = json_decode($response->getContent() ?: 'null', true, 512, JSON_THROW_ON_ERROR); + self::assertIsArray($data); + self::assertSame(400, $data['status'] ?? null); + self::assertSame('Validation failed', $data['detail'] ?? null); + self::assertArrayHasKey('violations', $data); + } +}