diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7a53853..ad484f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,8 +55,8 @@ jobs: - # Run AsyncAPI Validation name: AsyncAPI Validation run: | - docker run --rm -v $(pwd):/app asyncapi/cli:1.3.0 validate /app/var/asyncapi.yaml - docker run --rm -v $(pwd):/app asyncapi/cli:1.3.0 validate /app/var/asyncapi.json + docker run --rm -v $(pwd):/app asyncapi/cli:1.4.4 validate /app/var/asyncapi.yaml + docker run --rm -v $(pwd):/app asyncapi/cli:1.4.4 validate /app/var/asyncapi.json - # Upload Coverage to Coveralls name: Coveralls diff --git a/.github/workflows/demo.yml b/.github/workflows/demo.yml new file mode 100644 index 0000000..16a431e --- /dev/null +++ b/.github/workflows/demo.yml @@ -0,0 +1,39 @@ +name: CI + +on: + push: ~ + pull_request: ~ + workflow_dispatch: ~ + +jobs: + demo: + runs-on: ubuntu-latest + name: CI Demo - PHP ${{ matrix.php }} + strategy: + matrix: + php: [8.2, 8.3] + + steps: + - # Copies the repository files to the Action Runner + name: Checkout Repository + uses: actions/checkout@v4 + + - # Installs PHP and other necessary tools + name: Setup PHP + uses: shivammathur/setup-php@2.29.0 + with: + php-version: ${{ matrix.php }} + + - # Installs and caches PHP dependencies + name: Install Dependencies + uses: ramsey/composer-install@2.2.0 + with: + working-directory: example + + - # Validates composer.json structure and required fields + name: Validate composer.json + run: cd example && composer validate --ansi --strict --no-check-publish + + - # Runs unit and integration tests, like phpspec, phpunit etc. + name: Run Tests + run: cd example && composer test diff --git a/README.md b/README.md index 1d97a39..1864b09 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ # Async API Symfony Bundle +The library was inspired by [nelmio/api-doc-bundle](https://github.com/nelmio/NelmioApiDocBundle); To create a code-first experience +for PHP and Symfony engineers. This piece of software enables you to document events and messages via PHP built-in Attributes. + +Features +* Code-first async messages documentation +* Built-in ability to present code powered by [Async API React Component](https://github.com/asyncapi/asyncapi-react) +* Automated documentation powered by PHP Reflection + ## Installation ```bash diff --git a/example/composer.json b/example/composer.json index f3886b6..8fd8746 100644 --- a/example/composer.json +++ b/example/composer.json @@ -5,11 +5,16 @@ "require": { "php": ">=8.2", "ferror/asyncapi-doc-bundle": "dev-master", - "symfony/console": "6.3.*", + "symfony/console": "6.4.*", "symfony/flex": "^2", - "symfony/framework-bundle": "6.3.*", - "symfony/runtime": "6.3.*", - "symfony/yaml": "6.3.*" + "symfony/framework-bundle": "6.4.*", + "symfony/runtime": "6.4.*", + "symfony/yaml": "6.4.*" + }, + "require-dev": { + "phpunit/phpunit": "^10.5", + "symfony/phpunit-bridge": "6.4.*", + "symfony/browser-kit": "6.4.*" }, "config": { "allow-plugins": { @@ -26,7 +31,7 @@ }, "autoload-dev": { "psr-4": { - "App\\Tests\\": "tests/" + "App\\": "tests/" } }, "repositories": { @@ -50,7 +55,10 @@ "extra": { "symfony": { "allow-contrib": false, - "require": "6.3.*" + "require": "6.4.*" } + }, + "scripts": { + "test": "vendor/bin/phpunit" } } diff --git a/example/composer.lock b/example/composer.lock index 93c68a7..3cb29c7 100644 --- a/example/composer.lock +++ b/example/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": "de97c40fbb1b93dd2a892cec4d75be9e", + "content-hash": "5bac9f3362608814183c4756047eb67d", "packages": [ { "name": "ferror/asyncapi-doc-bundle", @@ -12,22 +12,26 @@ "dist": { "type": "path", "url": "..", - "reference": "7bb19470f4dff59b0218f4811446f9896a44874a" + "reference": "39e681aa9008f40a3bc54bcea3fe943de52d845d" }, "require": { "php": "^8.2", - "symfony/console": "^6.3", - "symfony/dependency-injection": "^6.3", - "symfony/http-foundation": "^6.3", - "symfony/http-kernel": "^6.3", - "symfony/yaml": "^6.3" + "symfony/config": "^6.4|^7.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/yaml": "^6.4|^7.0" }, "require-dev": { "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", + "phpstan/phpstan-symfony": "^1.3", "phpunit/phpunit": "^10.3", - "symfony/browser-kit": "^6.3", - "symfony/framework-bundle": "^6.3", - "symfony/var-dumper": "^6.3" + "qossmic/deptrac-shim": "^1.0", + "symfony/browser-kit": "^6.4|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -45,10 +49,13 @@ "vendor/bin/phpunit" ], "coverage": [ - "vendor/bin/phpunit --coverage-html=var/coverage" + "vendor/bin/phpunit --coverage-html=var/coverage --coverage-clover var/coverage/clover.xml" ], "analyse": [ "vendor/bin/phpstan analyse" + ], + "deptrac": [ + "vendor/bin/deptrac analyse" ] }, "license": [ @@ -262,16 +269,16 @@ }, { "name": "symfony/cache", - "version": "v6.3.4", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "e60d00b4f633efa4c1ef54e77c12762d9073e7b3" + "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/e60d00b4f633efa4c1ef54e77c12762d9073e7b3", - "reference": "e60d00b4f633efa4c1ef54e77c12762d9073e7b3", + "url": "https://api.github.com/repos/symfony/cache/zipball/14a75869bbb41cb35bc5d9d322473928c6f3f978", + "reference": "14a75869bbb41cb35bc5d9d322473928c6f3f978", "shasum": "" }, "require": { @@ -280,7 +287,7 @@ "psr/log": "^1.1|^2|^3", "symfony/cache-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3", - "symfony/var-exporter": "^6.2.10" + "symfony/var-exporter": "^6.3.6|^7.0" }, "conflict": { "doctrine/dbal": "<2.13.1", @@ -295,15 +302,15 @@ }, "require-dev": { "cache/integration-tests": "dev-master", - "doctrine/dbal": "^2.13.1|^3.0", + "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", "psr/simple-cache": "^1.0|^2.0|^3.0", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -338,7 +345,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.3.4" + "source": "https://github.com/symfony/cache/tree/v6.4.2" }, "funding": [ { @@ -354,20 +361,20 @@ "type": "tidelift" } ], - "time": "2023-08-05T09:10:27+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "ad945640ccc0ae6e208bcea7d7de4b39b569896b" + "reference": "1d74b127da04ffa87aa940abe15446fa89653778" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/ad945640ccc0ae6e208bcea7d7de4b39b569896b", - "reference": "ad945640ccc0ae6e208bcea7d7de4b39b569896b", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1d74b127da04ffa87aa940abe15446fa89653778", + "reference": "1d74b127da04ffa87aa940abe15446fa89653778", "shasum": "" }, "require": { @@ -414,7 +421,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.4.0" }, "funding": [ { @@ -430,26 +437,26 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2023-09-25T12:52:38+00:00" }, { "name": "symfony/config", - "version": "v6.3.2", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467" + "reference": "5d33e0fb707d603330e0edfd4691803a1253572e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", - "reference": "b47ca238b03e7b0d7880ffd1cf06e8d637ca1467", + "url": "https://api.github.com/repos/symfony/config/zipball/5d33e0fb707d603330e0edfd4691803a1253572e", + "reference": "5d33e0fb707d603330e0edfd4691803a1253572e", "shasum": "" }, "require": { "php": ">=8.1", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/filesystem": "^5.4|^6.0", + "symfony/filesystem": "^5.4|^6.0|^7.0", "symfony/polyfill-ctype": "~1.8" }, "conflict": { @@ -457,11 +464,11 @@ "symfony/service-contracts": "<2.5" }, "require-dev": { - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/messenger": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/yaml": "^5.4|^6.0" + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -489,7 +496,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.3.2" + "source": "https://github.com/symfony/config/tree/v6.4.0" }, "funding": [ { @@ -505,20 +512,20 @@ "type": "tidelift" } ], - "time": "2023-07-19T20:22:16+00:00" + "time": "2023-11-09T08:28:32+00:00" }, { "name": "symfony/console", - "version": "v6.3.4", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", - "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", + "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", "shasum": "" }, "require": { @@ -526,7 +533,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0" + "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { "symfony/dependency-injection": "<5.4", @@ -540,12 +547,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -579,7 +590,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.4" + "source": "https://github.com/symfony/console/tree/v6.4.2" }, "funding": [ { @@ -595,20 +606,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T10:10:12+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.3.4", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "68a5a9570806a087982f383f6109c5e925892a49" + "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/68a5a9570806a087982f383f6109c5e925892a49", - "reference": "68a5a9570806a087982f383f6109c5e925892a49", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/226ea431b1eda6f0d9f5a4b278757171960bb195", + "reference": "226ea431b1eda6f0d9f5a4b278757171960bb195", "shasum": "" }, "require": { @@ -616,7 +627,7 @@ "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10" + "symfony/var-exporter": "^6.2.10|^7.0" }, "conflict": { "ext-psr": "<1.1|>=2", @@ -630,9 +641,9 @@ "symfony/service-implementation": "1.1|2.0|3.0" }, "require-dev": { - "symfony/config": "^6.1", - "symfony/expression-language": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" + "symfony/config": "^6.1|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -660,7 +671,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.3.4" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.2" }, "funding": [ { @@ -676,11 +687,11 @@ "type": "tidelift" } ], - "time": "2023-08-16T17:55:17+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -727,7 +738,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.4.0" }, "funding": [ { @@ -747,30 +758,31 @@ }, { "name": "symfony/error-handler", - "version": "v6.3.2", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "85fd65ed295c4078367c784e8a5a6cee30348b7a" + "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/85fd65ed295c4078367c784e8a5a6cee30348b7a", - "reference": "85fd65ed295c4078367c784e8a5a6cee30348b7a", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/c873490a1c97b3a0a4838afc36ff36c112d02788", + "reference": "c873490a1c97b3a0a4838afc36ff36c112d02788", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0" + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "conflict": { - "symfony/deprecation-contracts": "<2.5" + "symfony/deprecation-contracts": "<2.5", + "symfony/http-kernel": "<6.4" }, "require-dev": { "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/serializer": "^5.4|^6.0" + "symfony/http-kernel": "^6.4|^7.0", + "symfony/serializer": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -801,7 +813,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.3.2" + "source": "https://github.com/symfony/error-handler/tree/v6.4.0" }, "funding": [ { @@ -817,20 +829,20 @@ "type": "tidelift" } ], - "time": "2023-07-16T17:05:46+00:00" + "time": "2023-10-18T09:43:34+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.3.2", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e" + "reference": "e95216850555cd55e71b857eb9d6c2674124603a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/adb01fe097a4ee930db9258a3cc906b5beb5cf2e", - "reference": "adb01fe097a4ee930db9258a3cc906b5beb5cf2e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e95216850555cd55e71b857eb9d6c2674124603a", + "reference": "e95216850555cd55e71b857eb9d6c2674124603a", "shasum": "" }, "require": { @@ -847,13 +859,13 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/error-handler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0" + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -881,7 +893,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.3.2" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.2" }, "funding": [ { @@ -897,11 +909,11 @@ "type": "tidelift" } ], - "time": "2023-07-06T06:56:43+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.3.0", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", @@ -957,7 +969,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" }, "funding": [ { @@ -977,16 +989,16 @@ }, { "name": "symfony/filesystem", - "version": "v6.3.1", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" + "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", - "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/952a8cb588c3bc6ce76f6023000fb932f16a6e59", + "reference": "952a8cb588c3bc6ce76f6023000fb932f16a6e59", "shasum": "" }, "require": { @@ -1020,7 +1032,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.3.1" + "source": "https://github.com/symfony/filesystem/tree/v6.4.0" }, "funding": [ { @@ -1036,27 +1048,27 @@ "type": "tidelift" } ], - "time": "2023-06-01T08:30:39+00:00" + "time": "2023-07-26T17:27:13+00:00" }, { "name": "symfony/finder", - "version": "v6.3.3", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e" + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/9915db259f67d21eefee768c1abcf1cc61b1fc9e", - "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e", + "url": "https://api.github.com/repos/symfony/finder/zipball/11d736e97f116ac375a81f96e662911a34cd50ce", + "reference": "11d736e97f116ac375a81f96e662911a34cd50ce", "shasum": "" }, "require": { "php": ">=8.1" }, "require-dev": { - "symfony/filesystem": "^6.0" + "symfony/filesystem": "^6.0|^7.0" }, "type": "library", "autoload": { @@ -1084,7 +1096,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.3.3" + "source": "https://github.com/symfony/finder/tree/v6.4.0" }, "funding": [ { @@ -1100,20 +1112,20 @@ "type": "tidelift" } ], - "time": "2023-07-31T08:31:44+00:00" + "time": "2023-10-31T17:30:12+00:00" }, { "name": "symfony/flex", - "version": "v2.3.3", + "version": "v2.4.3", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "9c402af768c6c9f8126a9ffa192ecf7c16581e35" + "reference": "6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/9c402af768c6c9f8126a9ffa192ecf7c16581e35", - "reference": "9c402af768c6c9f8126a9ffa192ecf7c16581e35", + "url": "https://api.github.com/repos/symfony/flex/zipball/6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1", + "reference": "6b44ac75c7f07f48159ec36c2d21ef8cf48a21b1", "shasum": "" }, "require": { @@ -1149,7 +1161,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.3.3" + "source": "https://github.com/symfony/flex/tree/v2.4.3" }, "funding": [ { @@ -1165,38 +1177,38 @@ "type": "tidelift" } ], - "time": "2023-08-04T09:02:35+00:00" + "time": "2024-01-02T11:08:32+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.3.4", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "f822f54ff05cd88878910b4559f66c12176d952c" + "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/f822f54ff05cd88878910b4559f66c12176d952c", - "reference": "f822f54ff05cd88878910b4559f66c12176d952c", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/c26a221e0462027d1f9d4a802ed63f8ab07a43d0", + "reference": "c26a221e0462027d1f9d4a802ed63f8ab07a43d0", "shasum": "" }, "require": { "composer-runtime-api": ">=2.1", "ext-xml": "*", "php": ">=8.1", - "symfony/cache": "^5.4|^6.0", - "symfony/config": "^6.1", - "symfony/dependency-injection": "^6.3.1", + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.1", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", - "symfony/http-foundation": "^6.3", - "symfony/http-kernel": "^6.3", + "symfony/error-handler": "^6.1|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/filesystem": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4", "symfony/polyfill-mbstring": "~1.0", - "symfony/routing": "^5.4|^6.0" + "symfony/routing": "^6.4|^7.0" }, "conflict": { "doctrine/annotations": "<1.13.1", @@ -1204,67 +1216,71 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/asset": "<5.4", + "symfony/asset-mapper": "<6.4", "symfony/clock": "<6.3", - "symfony/console": "<5.4", - "symfony/dom-crawler": "<6.3", + "symfony/console": "<5.4|>=7.0", + "symfony/dom-crawler": "<6.4", "symfony/dotenv": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<6.3", "symfony/lock": "<5.4", "symfony/mailer": "<5.4", "symfony/messenger": "<6.3", - "symfony/mime": "<6.2", + "symfony/mime": "<6.4", "symfony/property-access": "<5.4", "symfony/property-info": "<5.4", + "symfony/scheduler": "<6.4", "symfony/security-core": "<5.4", "symfony/security-csrf": "<5.4", - "symfony/serializer": "<6.3", + "symfony/serializer": "<6.4", "symfony/stopwatch": "<5.4", - "symfony/translation": "<6.2.8", + "symfony/translation": "<6.4", "symfony/twig-bridge": "<5.4", "symfony/twig-bundle": "<5.4", - "symfony/validator": "<6.3", - "symfony/web-profiler-bundle": "<5.4", - "symfony/workflow": "<5.4" + "symfony/validator": "<6.4", + "symfony/web-profiler-bundle": "<6.4", + "symfony/workflow": "<6.4" }, "require-dev": { "doctrine/annotations": "^1.13.1|^2", "doctrine/persistence": "^1.3|^2|^3", + "dragonmantank/cron-expression": "^3.1", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", - "symfony/asset": "^5.4|^6.0", - "symfony/asset-mapper": "^6.3", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/clock": "^6.2", - "symfony/console": "^5.4.9|^6.0.9", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dom-crawler": "^6.3", - "symfony/dotenv": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/form": "^5.4|^6.0", - "symfony/html-sanitizer": "^6.1", - "symfony/http-client": "^6.3", - "symfony/lock": "^5.4|^6.0", - "symfony/mailer": "^5.4|^6.0", - "symfony/messenger": "^6.3", - "symfony/mime": "^6.2", - "symfony/notifier": "^5.4|^6.0", + "seld/jsonlint": "^1.10", + "symfony/asset": "^5.4|^6.0|^7.0", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/clock": "^6.2|^7.0", + "symfony/console": "^5.4.9|^6.0.9|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dom-crawler": "^6.4|^7.0", + "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/html-sanitizer": "^6.1|^7.0", + "symfony/http-client": "^6.3|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/mailer": "^5.4|^6.0|^7.0", + "symfony/messenger": "^6.3|^7.0", + "symfony/mime": "^6.4|^7.0", + "symfony/notifier": "^5.4|^6.0|^7.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/process": "^5.4|^6.0", - "symfony/property-info": "^5.4|^6.0", - "symfony/rate-limiter": "^5.4|^6.0", - "symfony/scheduler": "^6.3", - "symfony/security-bundle": "^5.4|^6.0", - "symfony/semaphore": "^5.4|^6.0", - "symfony/serializer": "^6.3", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/string": "^5.4|^6.0", - "symfony/translation": "^6.2.8", - "symfony/twig-bundle": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^6.3", - "symfony/web-link": "^5.4|^6.0", - "symfony/workflow": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0", + "symfony/scheduler": "^6.4|^7.0", + "symfony/security-bundle": "^5.4|^6.0|^7.0", + "symfony/semaphore": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/string": "^5.4|^6.0|^7.0", + "symfony/translation": "^6.4|^7.0", + "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/web-link": "^5.4|^6.0|^7.0", + "symfony/workflow": "^6.4|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0", "twig/twig": "^2.10|^3.0" }, "type": "symfony-bundle", @@ -1293,7 +1309,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.3.4" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.2" }, "funding": [ { @@ -1309,20 +1325,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T18:04:38+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.3.4", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "cac1556fdfdf6719668181974104e6fcfa60e844" + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cac1556fdfdf6719668181974104e6fcfa60e844", - "reference": "cac1556fdfdf6719668181974104e6fcfa60e844", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/172d807f9ef3fc3fbed8377cc57c20d389269271", + "reference": "172d807f9ef3fc3fbed8377cc57c20d389269271", "shasum": "" }, "require": { @@ -1332,17 +1348,17 @@ "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.2" + "symfony/cache": "<6.3" }, "require-dev": { - "doctrine/dbal": "^2.13.1|^3.0", + "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", - "symfony/mime": "^5.4|^6.0", - "symfony/rate-limiter": "^5.2|^6.0" + "symfony/cache": "^6.3|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/rate-limiter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -1370,7 +1386,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.3.4" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.2" }, "funding": [ { @@ -1386,29 +1402,29 @@ "type": "tidelift" } ], - "time": "2023-08-22T08:20:46+00:00" + "time": "2023-12-27T22:16:42+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.3.4", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb" + "reference": "13e8387320b5942d0dc408440c888e2d526efef4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb", - "reference": "36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/13e8387320b5942d0dc408440c888e2d526efef4", + "reference": "13e8387320b5942d0dc408440c888e2d526efef4", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/error-handler": "^6.3", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^6.3.4", + "symfony/error-handler": "^6.4|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -1416,7 +1432,7 @@ "symfony/cache": "<5.4", "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.3.4", + "symfony/dependency-injection": "<6.4", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", @@ -1426,7 +1442,7 @@ "symfony/translation": "<5.4", "symfony/translation-contracts": "<2.5", "symfony/twig-bridge": "<5.4", - "symfony/validator": "<5.4", + "symfony/validator": "<6.4", "symfony/var-dumper": "<6.3", "twig/twig": "<2.13" }, @@ -1435,26 +1451,26 @@ }, "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", - "symfony/browser-kit": "^5.4|^6.0", - "symfony/clock": "^6.2", - "symfony/config": "^6.1", - "symfony/console": "^5.4|^6.0", - "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^6.3.4", - "symfony/dom-crawler": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/finder": "^5.4|^6.0", + "symfony/browser-kit": "^5.4|^6.0|^7.0", + "symfony/clock": "^6.2|^7.0", + "symfony/config": "^6.1|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dom-crawler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", "symfony/http-client-contracts": "^2.5|^3", - "symfony/process": "^5.4|^6.0", - "symfony/property-access": "^5.4.5|^6.0.5", - "symfony/routing": "^5.4|^6.0", - "symfony/serializer": "^6.3", - "symfony/stopwatch": "^5.4|^6.0", - "symfony/translation": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4.5|^6.0.5|^7.0", + "symfony/routing": "^5.4|^6.0|^7.0", + "symfony/serializer": "^6.3|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4|^6.0|^7.0", "symfony/translation-contracts": "^2.5|^3", - "symfony/uid": "^5.4|^6.0", - "symfony/validator": "^6.3", - "symfony/var-exporter": "^6.2", + "symfony/uid": "^5.4|^6.0|^7.0", + "symfony/validator": "^6.4|^7.0", + "symfony/var-exporter": "^6.2|^7.0", "twig/twig": "^2.13|^3.0.4" }, "type": "library", @@ -1483,7 +1499,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.3.4" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.2" }, "funding": [ { @@ -1499,7 +1515,7 @@ "type": "tidelift" } ], - "time": "2023-08-26T13:54:49+00:00" + "time": "2023-12-30T15:31:44+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -1831,16 +1847,16 @@ }, { "name": "symfony/routing", - "version": "v6.3.3", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "e7243039ab663822ff134fbc46099b5fdfa16f6a" + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/e7243039ab663822ff134fbc46099b5fdfa16f6a", - "reference": "e7243039ab663822ff134fbc46099b5fdfa16f6a", + "url": "https://api.github.com/repos/symfony/routing/zipball/98eab13a07fddc85766f1756129c69f207ffbc21", + "reference": "98eab13a07fddc85766f1756129c69f207ffbc21", "shasum": "" }, "require": { @@ -1856,11 +1872,11 @@ "require-dev": { "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^6.2", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/expression-language": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" + "symfony/config": "^6.2|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -1894,7 +1910,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.3.3" + "source": "https://github.com/symfony/routing/tree/v6.4.2" }, "funding": [ { @@ -1910,20 +1926,20 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-12-29T15:34:34+00:00" }, { "name": "symfony/runtime", - "version": "v6.3.2", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "d5c09493647a0c1a16e6c8da308098e840d1164f" + "reference": "86539231fadfdc7f7e9911d6fa7ed84a606e7d34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/d5c09493647a0c1a16e6c8da308098e840d1164f", - "reference": "d5c09493647a0c1a16e6c8da308098e840d1164f", + "url": "https://api.github.com/repos/symfony/runtime/zipball/86539231fadfdc7f7e9911d6fa7ed84a606e7d34", + "reference": "86539231fadfdc7f7e9911d6fa7ed84a606e7d34", "shasum": "" }, "require": { @@ -1935,10 +1951,10 @@ }, "require-dev": { "composer/composer": "^1.0.2|^2.0", - "symfony/console": "^5.4.9|^6.0.9", - "symfony/dotenv": "^5.4|^6.0", - "symfony/http-foundation": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0" + "symfony/console": "^5.4.9|^6.0.9|^7.0", + "symfony/dotenv": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0" }, "type": "composer-plugin", "extra": { @@ -1973,7 +1989,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v6.3.2" + "source": "https://github.com/symfony/runtime/tree/v6.4.0" }, "funding": [ { @@ -1989,25 +2005,25 @@ "type": "tidelift" } ], - "time": "2023-07-16T17:05:46+00:00" + "time": "2023-10-18T09:43:34+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.3.0", + "version": "v3.4.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", - "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", + "reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "shasum": "" }, "require": { "php": ">=8.1", - "psr/container": "^2.0" + "psr/container": "^1.1|^2.0" }, "conflict": { "ext-psr": "<1.1|>=2" @@ -2055,7 +2071,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.4.1" }, "funding": [ { @@ -2071,20 +2087,20 @@ "type": "tidelift" } ], - "time": "2023-05-23T14:45:45+00:00" + "time": "2023-12-26T14:02:43+00:00" }, { "name": "symfony/string", - "version": "v6.3.2", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "53d1a83225002635bca3482fcbf963001313fb68" + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/53d1a83225002635bca3482fcbf963001313fb68", - "reference": "53d1a83225002635bca3482fcbf963001313fb68", + "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", "shasum": "" }, "require": { @@ -2098,11 +2114,11 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/intl": "^6.2", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -2141,7 +2157,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.3.2" + "source": "https://github.com/symfony/string/tree/v6.4.2" }, "funding": [ { @@ -2157,20 +2173,20 @@ "type": "tidelift" } ], - "time": "2023-07-05T08:41:27+00:00" + "time": "2023-12-10T16:15:48+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.3.4", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "2027be14f8ae8eae999ceadebcda5b4909b81d45" + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2027be14f8ae8eae999ceadebcda5b4909b81d45", - "reference": "2027be14f8ae8eae999ceadebcda5b4909b81d45", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", + "reference": "68d6573ec98715ddcae5a0a85bee3c1c27a4c33f", "shasum": "" }, "require": { @@ -2183,10 +2199,11 @@ }, "require-dev": { "ext-iconv": "*", - "symfony/console": "^5.4|^6.0", - "symfony/http-kernel": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", "twig/twig": "^2.13|^3.0.4" }, "bin": [ @@ -2225,7 +2242,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.3.4" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.2" }, "funding": [ { @@ -2241,27 +2258,28 @@ "type": "tidelift" } ], - "time": "2023-08-24T14:51:05+00:00" + "time": "2023-12-28T19:16:56+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.3.4", + "version": "v6.4.2", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691" + "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/df1f8aac5751871b83d30bf3e2c355770f8f0691", - "reference": "df1f8aac5751871b83d30bf3e2c355770f8f0691", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/5fe9a0021b8d35e67d914716ec8de50716a68e7e", + "reference": "5fe9a0021b8d35e67d914716ec8de50716a68e7e", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { - "symfony/var-dumper": "^5.4|^6.0" + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -2299,7 +2317,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.3.4" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.2" }, "funding": [ { @@ -2315,20 +2333,20 @@ "type": "tidelift" } ], - "time": "2023-08-16T18:14:47+00:00" + "time": "2023-12-27T08:18:35+00:00" }, { "name": "symfony/yaml", - "version": "v6.3.3", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "e23292e8c07c85b971b44c1c4b87af52133e2add" + "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e23292e8c07c85b971b44c1c4b87af52133e2add", - "reference": "e23292e8c07c85b971b44c1c4b87af52133e2add", + "url": "https://api.github.com/repos/symfony/yaml/zipball/4f9237a1bb42455d609e6687d2613dde5b41a587", + "reference": "4f9237a1bb42455d609e6687d2613dde5b41a587", "shasum": "" }, "require": { @@ -2340,7 +2358,7 @@ "symfony/console": "<5.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0" + "symfony/console": "^5.4|^6.0|^7.0" }, "bin": [ "Resources/bin/yaml-lint" @@ -2371,7 +2389,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.3.3" + "source": "https://github.com/symfony/yaml/tree/v6.4.0" }, "funding": [ { @@ -2387,10 +2405,1909 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-11-06T11:00:25+00:00" + } + ], + "packages-dev": [ + { + "name": "masterminds/html5", + "version": "2.8.1", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", + "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" + }, + "time": "2023-05-10T11:58:31+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v5.0.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4a21235f7e56e713259a6f76bf4b5ea08502b9dc", + "reference": "4a21235f7e56e713259a6f76bf4b5ea08502b9dc", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-tokenizer": "*", + "php": ">=7.4" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v5.0.0" + }, + "time": "2024-01-07T17:17:35+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.11", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "78c3b7625965c2513ee96569a4dbb62601784145" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/78c3b7625965c2513ee96569a4dbb62601784145", + "reference": "78c3b7625965c2513ee96569a4dbb62601784145", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.11" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T15:38:30+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T06:24:48+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-31T14:07:24+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.5.9", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe", + "reference": "0bd663704f0165c9e76fe4f06ffa6a1ca727fdbe", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.5", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.1", + "sebastian/global-state": "^6.0.1", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.5-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.9" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-01-22T14:35:40+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:15+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-14T13:18:12+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.2.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "68ff824baeae169ec9f2137158ee529584553799" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:37:17+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/fbf413a49e54f6b9b17e12d900ac7f6101591b7f", + "reference": "fbf413a49e54f6b9b17e12d900ac7f6101591b7f", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T10:55:06+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-04-11T05:39:26+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/64f51654862e0f5e318db7e9dcc2292c63cdbddc", + "reference": "64f51654862e0f5e318db7e9dcc2292c63cdbddc", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-09-24T13:22:09+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-07-19T07:19:23+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-21T08:38:20+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:05:40+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "symfony/browser-kit", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/browser-kit.git", + "reference": "a3bb210e001580ec75e1d02b27fae3452e6bf502" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/a3bb210e001580ec75e1d02b27fae3452e6bf502", + "reference": "a3bb210e001580ec75e1d02b27fae3452e6bf502", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/dom-crawler": "^5.4|^6.0|^7.0" + }, + "require-dev": { + "symfony/css-selector": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\BrowserKit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/browser-kit/tree/v6.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-10-31T08:18:17+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "14ff4fd2a5c8969d6158dbe7ef5b17d6a9c6ba33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/14ff4fd2a5c8969d6158dbe7ef5b17d6a9c6ba33", + "reference": "14ff4fd2a5c8969d6158dbe7ef5b17d6a9c6ba33", + "shasum": "" + }, + "require": { + "masterminds/html5": "^2.6", + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases DOM navigation for HTML and XML documents", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-11-20T16:41:16+00:00" + }, + { + "name": "symfony/phpunit-bridge", + "version": "v6.4.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "bd0455b7888e4adac29cf175d819c51f88fed942" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/bd0455b7888e4adac29cf175d819c51f88fed942", + "reference": "bd0455b7888e4adac29cf175d819c51f88fed942", + "shasum": "" + }, + "require": { + "php": ">=7.1.3" + }, + "conflict": { + "phpunit/phpunit": "<7.5|9.1.2" + }, + "require-dev": { + "symfony/deprecation-contracts": "^2.5|^3.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/polyfill-php81": "^1.27" + }, + "bin": [ + "bin/simple-phpunit" + ], + "type": "symfony-bridge", + "extra": { + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Bridge\\PhpUnit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides utilities for PHPUnit, especially user deprecation notices management", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-12-19T09:12:31+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "reference": "b2ad5003ca10d4ee50a12da31de12a5774ba6b96", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.2" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2023-11-20T00:12:19+00:00" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": { diff --git a/example/config/packages/library.yaml b/example/config/packages/library.yaml index f1d0422..2db9db0 100644 --- a/example/config/packages/library.yaml +++ b/example/config/packages/library.yaml @@ -2,4 +2,5 @@ ferror_asyncapi_doc_bundle: title: 'Service Example API' version: '1.2.3' events: - - App\ProductCreated \ No newline at end of file + - App\ProductCreated + - App\UserSignedUp diff --git a/example/phpunit.xml b/example/phpunit.xml new file mode 100644 index 0000000..c101065 --- /dev/null +++ b/example/phpunit.xml @@ -0,0 +1,26 @@ + + + + + tests + + + + + + src + + + diff --git a/example/src/UserSignedUp.php b/example/src/UserSignedUp.php new file mode 100644 index 0000000..14799fe --- /dev/null +++ b/example/src/UserSignedUp.php @@ -0,0 +1,19 @@ +request(Request::METHOD_GET, '/asyncapi.json'); + + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + } +} diff --git a/example/tests/UserInterfaceControllerTest.php b/example/tests/UserInterfaceControllerTest.php new file mode 100644 index 0000000..70ffa64 --- /dev/null +++ b/example/tests/UserInterfaceControllerTest.php @@ -0,0 +1,21 @@ +request(Request::METHOD_GET, '/asyncapi'); + + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + } +} diff --git a/example/tests/YamlSpecificationControllerTest.php b/example/tests/YamlSpecificationControllerTest.php new file mode 100644 index 0000000..a635c2d --- /dev/null +++ b/example/tests/YamlSpecificationControllerTest.php @@ -0,0 +1,21 @@ +request(Request::METHOD_GET, '/asyncapi.yaml'); + + $this->assertEquals(200, $client->getResponse()->getStatusCode()); + } +} diff --git a/src/Attribute/AbstractProperty.php b/src/Attribute/AbstractProperty.php index 4d1038f..7dde835 100644 --- a/src/Attribute/AbstractProperty.php +++ b/src/Attribute/AbstractProperty.php @@ -4,7 +4,7 @@ namespace Ferror\AsyncapiDocBundle\Attribute; -abstract class AbstractProperty +abstract class AbstractProperty implements PropertyInterface { public function __construct( public string $name, diff --git a/src/Attribute/Message.php b/src/Attribute/Message.php index 4281773..3df5891 100644 --- a/src/Attribute/Message.php +++ b/src/Attribute/Message.php @@ -7,10 +7,10 @@ use Attribute; #[Attribute(Attribute::TARGET_CLASS)] -readonly class Message implements PropertyInterface +class Message { /** - * @param PropertyInterface[] $properties + * @param array $properties */ public function __construct( public string $name, @@ -25,4 +25,30 @@ public function toArray(): array 'properties' => array_map(static fn(PropertyInterface $property) => $property->toArray(), $this->properties), ]; } + + public function addProperty(Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject $property): void + { + $this->properties[] = $property; + } + + public function enrich(self $self): self + { + // UPDATE EXISTING + foreach ($this->properties as $property) { + foreach ($self->properties as $selfProperty) { + $property->enrich($selfProperty); + } + } + + // ADD MISSING + $propertiesNames = array_map(fn ($property) => $property->name, $this->properties); + + foreach ($self->properties as $property) { + if (!in_array($property->name, $propertiesNames, true)) { + $this->properties[] = $property; + } + } + + return $this; + } } diff --git a/src/Attribute/Property.php b/src/Attribute/Property.php index 0213900..a9848a5 100644 --- a/src/Attribute/Property.php +++ b/src/Attribute/Property.php @@ -9,14 +9,14 @@ use Ferror\AsyncapiDocBundle\Schema\PropertyType; #[Attribute(Attribute::TARGET_PROPERTY)] -class Property extends AbstractProperty implements PropertyInterface +class Property extends AbstractProperty { public function __construct( string $name, string $description = '', - public readonly PropertyType $type = PropertyType::STRING, - public readonly ?Format $format = null, - public readonly ?string $example = null, + public PropertyType $type = PropertyType::STRING, + public ?Format $format = null, + public ?string $example = null, bool $required = true, ) { parent::__construct($name, $description, $required); @@ -30,4 +30,25 @@ public function toArray(): array 'example' => $this->example, ]); } + + public function enrich(Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject $property): void + { + if ($property->name === $this->name && $property::class === $this::class) { + if (empty($this->format)) { + $this->format = $property->format; + } + + if ($this->type !== $property->type && $this->type === PropertyType::STRING) { + $this->type = $property->type; + } + + if (empty($this->example)) { + $this->example = $property->example; + } + + if (empty($this->description)) { + $this->description = $property->description; + } + } + } } diff --git a/src/Attribute/PropertyArray.php b/src/Attribute/PropertyArray.php index 3888c31..699a8a2 100644 --- a/src/Attribute/PropertyArray.php +++ b/src/Attribute/PropertyArray.php @@ -9,7 +9,7 @@ use Ferror\AsyncapiDocBundle\Schema\PropertyType; #[Attribute(Attribute::TARGET_PROPERTY)] -class PropertyArray extends AbstractProperty implements PropertyInterface +class PropertyArray extends AbstractProperty { public function __construct( string $name, @@ -31,4 +31,8 @@ public function toArray(): array 'itemsType' => $this->itemsType->value, ]); } + + public function enrich(Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject $property): void + { + } } diff --git a/src/Attribute/PropertyArrayObject.php b/src/Attribute/PropertyArrayObject.php index 287351c..f7052e1 100644 --- a/src/Attribute/PropertyArrayObject.php +++ b/src/Attribute/PropertyArrayObject.php @@ -8,7 +8,7 @@ use Ferror\AsyncapiDocBundle\Schema\Format; #[Attribute(Attribute::TARGET_PROPERTY)] -class PropertyArrayObject extends AbstractProperty implements PropertyInterface +class PropertyArrayObject extends AbstractProperty { public function __construct( string $name, @@ -29,4 +29,8 @@ public function toArray(): array 'example' => $this->example, ]); } + + public function enrich(Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject $property): void + { + } } diff --git a/src/Attribute/PropertyEnum.php b/src/Attribute/PropertyEnum.php index 8980e81..ad06327 100644 --- a/src/Attribute/PropertyEnum.php +++ b/src/Attribute/PropertyEnum.php @@ -7,12 +7,14 @@ use Attribute; use Ferror\AsyncapiDocBundle\PropertyTypeTranslator; use Ferror\AsyncapiDocBundle\Schema\Format; +use Ferror\AsyncapiDocBundle\Schema\PropertyType; use InvalidArgumentException; use ReflectionEnum; use ReflectionEnumBackedCase; +use ReflectionException; #[Attribute(Attribute::TARGET_PROPERTY)] -class PropertyEnum extends AbstractProperty implements PropertyInterface +class PropertyEnum extends AbstractProperty { public function __construct( string $name, @@ -25,6 +27,9 @@ public function __construct( parent::__construct($name, $description, $required); } + /** + * @throws ReflectionException + */ public function toArray(): array { $enum = new ReflectionEnum($this->enum); @@ -43,4 +48,17 @@ public function toArray(): array 'example' => $this->example, ]); } + + public function enrich(Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject $property): void + { + if ($property->name === $this->name && $property::class === $this::class) { + if (empty($this->format)) { + $this->format = $property->format; + } + + if (empty($this->example)) { + $this->example = $property->example; + } + } + } } diff --git a/src/Attribute/PropertyInterface.php b/src/Attribute/PropertyInterface.php index 1a3a873..be13bc7 100644 --- a/src/Attribute/PropertyInterface.php +++ b/src/Attribute/PropertyInterface.php @@ -7,4 +7,6 @@ interface PropertyInterface { public function toArray(): array; + + public function enrich(Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject $property): void; } diff --git a/src/Attribute/PropertyObject.php b/src/Attribute/PropertyObject.php index 1be5229..6aff996 100644 --- a/src/Attribute/PropertyObject.php +++ b/src/Attribute/PropertyObject.php @@ -7,7 +7,7 @@ use Attribute; #[Attribute(Attribute::TARGET_PROPERTY)] -class PropertyObject extends AbstractProperty implements PropertyInterface +class PropertyObject extends AbstractProperty { public function __construct( string $name, @@ -26,4 +26,8 @@ public function toArray(): array 'items' => array_map(static fn(PropertyInterface $property) => $property->toArray(), $this->items), ]); } + + public function enrich(Property|PropertyArray|PropertyEnum|PropertyObject|PropertyArrayObject $property): void + { + } } diff --git a/src/DocumentationEditor.php b/src/DocumentationEditor.php index cafbc13..de22c4f 100644 --- a/src/DocumentationEditor.php +++ b/src/DocumentationEditor.php @@ -4,31 +4,38 @@ namespace Ferror\AsyncapiDocBundle; -use Ferror\AsyncapiDocBundle\DocumentationStrategy\PrioritisedDocumentationStrategy; + +use Ferror\AsyncapiDocBundle\Attribute\Message; +use Ferror\AsyncapiDocBundle\DocumentationStrategy\PrioritisedDocumentationStrategyInterface; final readonly class DocumentationEditor { /** - * @param PrioritisedDocumentationStrategy[] $documentationStrategies + * @param PrioritisedDocumentationStrategyInterface[] $documentationStrategies */ public function __construct( private array $documentationStrategies, ) { } - public function document(string $class): array + public function document(string $class): Message { - $result = []; $strategies = []; foreach ($this->documentationStrategies as $documentationStrategy) { - $strategies[$documentationStrategy->priority] = $documentationStrategy->strategy; + $strategies[$documentationStrategy::getDefaultPriority()] = $documentationStrategy; } + $firstStrategy = array_shift($strategies); + + $documentedMessage = $firstStrategy->document($class); + foreach ($strategies as $documentationStrategy) { - $result = array_merge($result, $documentationStrategy->document($class)); + $message = $documentationStrategy->document($class); + + $documentedMessage = $documentedMessage->enrich($message); } - return $result; + return $documentedMessage; } } diff --git a/src/DocumentationStrategy/AttributeDocumentationStrategy.php b/src/DocumentationStrategy/AttributeDocumentationStrategy.php index 300d3da..9eb8cf7 100644 --- a/src/DocumentationStrategy/AttributeDocumentationStrategy.php +++ b/src/DocumentationStrategy/AttributeDocumentationStrategy.php @@ -7,15 +7,25 @@ use Ferror\AsyncapiDocBundle\Attribute\Message; use ReflectionAttribute; use ReflectionClass; +use ReflectionException; -final readonly class AttributeDocumentationStrategy implements DocumentationStrategyInterface +final readonly class AttributeDocumentationStrategy implements PrioritisedDocumentationStrategyInterface { public function __construct( private PropertyExtractor $propertyExtractor = new PropertyExtractor(), ) { } - public function document(string $class): array + public static function getDefaultPriority(): int + { + return 10; + } + + /** + * @throws DocumentationStrategyException + * @throws ReflectionException + */ + public function document(string $class): Message { $reflection = new ReflectionClass($class); /** @var ReflectionAttribute[] $messageAttributes */ @@ -25,10 +35,10 @@ public function document(string $class): array throw new DocumentationStrategyException('Error: class ' . $class . ' must have at least ' . Message::class . ' attribute.'); } - $message = $messageAttributes[0]->newInstance()->toArray(); + $message = $messageAttributes[0]->newInstance(); foreach ($this->propertyExtractor->extract($class) as $property) { - $message['properties'][] = $property->toArray(); + $message->addProperty($property); } return $message; diff --git a/src/DocumentationStrategy/DocumentationStrategyInterface.php b/src/DocumentationStrategy/DocumentationStrategyInterface.php index 526217f..f3e8c27 100644 --- a/src/DocumentationStrategy/DocumentationStrategyInterface.php +++ b/src/DocumentationStrategy/DocumentationStrategyInterface.php @@ -4,10 +4,12 @@ namespace Ferror\AsyncapiDocBundle\DocumentationStrategy; +use Ferror\AsyncapiDocBundle\Attribute\Message; + interface DocumentationStrategyInterface { /** * @param class-string $class */ - public function document(string $class): array; + public function document(string $class): Message; } diff --git a/src/DocumentationStrategy/PrioritisedDocumentationStrategy.php b/src/DocumentationStrategy/PrioritisedDocumentationStrategy.php deleted file mode 100644 index 4e41c5d..0000000 --- a/src/DocumentationStrategy/PrioritisedDocumentationStrategy.php +++ /dev/null @@ -1,14 +0,0 @@ - + * @return iterable * * @throws ReflectionException - * @throws RuntimeException */ public function extract(string $class): iterable { @@ -53,14 +51,12 @@ public function extract(string $class): iterable $propertyAttributes = $property->getAttributes(PropertyArrayObject::class); } - if (empty($propertyAttributes)) { - throw new RuntimeException('Property attribute for ' . $property->name . ' not found'); - } + if ($propertyAttributes) { + $propertyAttribute = $propertyAttributes[0]->newInstance(); + $propertyAttribute->name = $property->name; - $propertyAttribute = $propertyAttributes[0]->newInstance(); - $propertyAttribute->name = $property->name; - - yield $propertyAttribute; + yield $propertyAttribute; + } } } } diff --git a/src/DocumentationStrategy/ReflectionDocumentationStrategy.php b/src/DocumentationStrategy/ReflectionDocumentationStrategy.php index 1883781..b30d286 100644 --- a/src/DocumentationStrategy/ReflectionDocumentationStrategy.php +++ b/src/DocumentationStrategy/ReflectionDocumentationStrategy.php @@ -4,37 +4,64 @@ namespace Ferror\AsyncapiDocBundle\DocumentationStrategy; +use Ferror\AsyncapiDocBundle\Attribute\Message; +use Ferror\AsyncapiDocBundle\Attribute\Property; +use Ferror\AsyncapiDocBundle\Schema\PropertyType; +use ReflectionAttribute; use ReflectionClass; use ReflectionException; use ReflectionNamedType; -final readonly class ReflectionDocumentationStrategy implements DocumentationStrategyInterface +final readonly class ReflectionDocumentationStrategy implements PrioritisedDocumentationStrategyInterface { + public static function getDefaultPriority(): int + { + return 20; + } + /** * @param class-string $class * * @throws ReflectionException + * @throws DocumentationStrategyException */ - public function document(string $class): array + public function document(string $class): Message { $reflection = new ReflectionClass($class); - $properties = $reflection->getProperties(); + /** @var ReflectionAttribute[] $messageAttributes */ + $messageAttributes = $reflection->getAttributes(Message::class); + + if (empty($messageAttributes)) { + throw new DocumentationStrategyException('Error: class ' . $class . ' must have at least ' . Message::class . ' attribute.'); + } - $message['name'] = $reflection->getShortName(); + $message = $messageAttributes[0]->newInstance(); + $properties = $reflection->getProperties(); foreach ($properties as $property) { /** @var ReflectionNamedType|null $type */ $type = $property->getType(); $name = $property->getName(); - if ($type && !$type->allowsNull()) { - $message['required'][] = $name; + if (null === $type) { + break; } - $message['properties'][] = [ - 'name' => $name, - 'type' => $type?->getName(), - ]; + // ATM we don't support array types in ReflectionStrategy + if (in_array($type->getName(), ['array', 'object', 'resource'])) { + break; + } + + // ATM we support only builtin types like integer, string, boolean, float + if ($type->isBuiltin()) { + $message->addProperty( + new Property( + name: $name, + type: PropertyType::fromNative($type->getName()), + required: !$type->allowsNull(), + ) + ); + } } return $message; diff --git a/src/Schema/PropertyType.php b/src/Schema/PropertyType.php index 69554b1..a4d08e7 100644 --- a/src/Schema/PropertyType.php +++ b/src/Schema/PropertyType.php @@ -13,4 +13,14 @@ enum PropertyType: string case BOOLEAN = 'boolean'; case INTEGER = 'integer'; case FLOAT = 'number'; + + public static function fromNative(string $type): self + { + return match ($type) { + 'bool', 'boolean' => self::BOOLEAN, + 'int', 'integer' => self::INTEGER, + 'float', 'number' => self::FLOAT, + default => self::STRING, + }; + } } diff --git a/src/Schema/V2/MessageRenderer.php b/src/Schema/V2/MessageRenderer.php index 3026ea5..dab5bf9 100644 --- a/src/Schema/V2/MessageRenderer.php +++ b/src/Schema/V2/MessageRenderer.php @@ -16,19 +16,19 @@ public function render(array $document): array foreach ($document['properties'] as $property) { $properties[$property['name']]['type'] = PropertyTypeTranslator::translate($property['type']); - if (isset($property['description'])) { + if (!empty($property['description'])) { $properties[$property['name']]['description'] = $property['description']; } - if (isset($property['format'])) { + if (!empty($property['format'])) { $properties[$property['name']]['format'] = $property['format']; } - if (isset($property['example'])) { + if (!empty($property['example'])) { $properties[$property['name']]['example'] = $property['example']; } - if (isset($property['required'])) { + if (isset($property['required']) && $property['required']) { $required[] = $property['name']; } } diff --git a/src/Schema/V2/SchemaRenderer.php b/src/Schema/V2/SchemaRenderer.php index ca2285c..45dfc1c 100644 --- a/src/Schema/V2/SchemaRenderer.php +++ b/src/Schema/V2/SchemaRenderer.php @@ -5,14 +5,14 @@ namespace Ferror\AsyncapiDocBundle\Schema\V2; use Ferror\AsyncapiDocBundle\ClassFinder\ClassFinderInterface; -use Ferror\AsyncapiDocBundle\DocumentationStrategy\DocumentationStrategyInterface; +use Ferror\AsyncapiDocBundle\DocumentationEditor; use Ferror\AsyncapiDocBundle\SchemaRendererInterface; final readonly class SchemaRenderer implements SchemaRendererInterface { public function __construct( private ClassFinderInterface $classFinder, - private DocumentationStrategyInterface $documentationStrategy, + private DocumentationEditor $documentationEditor, private ChannelRenderer $channelRenderer, private MessageRenderer $messageRenderer, private InfoRenderer $infoRenderer, @@ -29,7 +29,8 @@ public function generate(): array $messages = []; foreach ($classes as $class) { - $document = $this->documentationStrategy->document($class); + $document = $this->documentationEditor->document($class); + $document = $document->toArray(); $channel = $this->channelRenderer->render($document); $message = $this->messageRenderer->render($document); diff --git a/src/Symfony/Bundle.php b/src/Symfony/Bundle.php index 84c1bad..f0052d2 100644 --- a/src/Symfony/Bundle.php +++ b/src/Symfony/Bundle.php @@ -4,6 +4,8 @@ namespace Ferror\AsyncapiDocBundle\Symfony; +use Ferror\AsyncapiDocBundle\Symfony\CompilerPass\DocumentationStrategyCompilerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle as SymfonyBundle; class Bundle extends SymfonyBundle @@ -12,4 +14,9 @@ public function getContainerExtension(): Extension { return new Extension(); } + + public function build(ContainerBuilder $container) + { + $container->addCompilerPass(new DocumentationStrategyCompilerPass()); + } } diff --git a/src/Symfony/CompilerPass/DocumentationStrategyCompilerPass.php b/src/Symfony/CompilerPass/DocumentationStrategyCompilerPass.php new file mode 100644 index 0000000..f9c4e36 --- /dev/null +++ b/src/Symfony/CompilerPass/DocumentationStrategyCompilerPass.php @@ -0,0 +1,27 @@ +findTaggedServiceIds('ferror.asyncapi_doc_bundle.documentation-strategy'); + + $documentationEditorDefinition = $container->getDefinition(DocumentationEditor::class); + + $taggedServices = array_map( + static fn ($serviceId) => new Reference($serviceId), + array_keys($taggedServices) + ); + + $documentationEditorDefinition->addArgument($taggedServices); + } +} diff --git a/src/Symfony/Console/DumpSpecificationConsole.php b/src/Symfony/Console/DumpSpecificationConsole.php index a601920..6fefaac 100644 --- a/src/Symfony/Console/DumpSpecificationConsole.php +++ b/src/Symfony/Console/DumpSpecificationConsole.php @@ -36,7 +36,7 @@ public function execute(InputInterface $input, OutputInterface $output): int if ($input->getArgument('class')) { $document = $this->documentationStrategy->document($input->getArgument('class')); - $schema = $this->messageRenderer->render($document); + $schema = $this->messageRenderer->render($document->toArray()); $io->writeln(Yaml::dump($schema, 10, 2)); diff --git a/src/Symfony/Extension.php b/src/Symfony/Extension.php index 19a2982..8fb7858 100644 --- a/src/Symfony/Extension.php +++ b/src/Symfony/Extension.php @@ -5,7 +5,9 @@ namespace Ferror\AsyncapiDocBundle\Symfony; use Ferror\AsyncapiDocBundle\ClassFinder\ManualClassFinder; +use Ferror\AsyncapiDocBundle\DocumentationEditor; use Ferror\AsyncapiDocBundle\DocumentationStrategy\AttributeDocumentationStrategy; +use Ferror\AsyncapiDocBundle\DocumentationStrategy\ReflectionDocumentationStrategy; use Ferror\AsyncapiDocBundle\Generator\GeneratorFactory; use Ferror\AsyncapiDocBundle\Generator\JsonGenerator; use Ferror\AsyncapiDocBundle\Generator\YamlGenerator; @@ -44,6 +46,12 @@ public function load(array $configs, ContainerBuilder $container): void $container ->register('ferror.asyncapi_doc_bundle.documentation.attributes', AttributeDocumentationStrategy::class) + ->addTag('ferror.asyncapi_doc_bundle.documentation-strategy') + ; + + $container + ->register('ferror.asyncapi_doc_bundle.documentation.reflection', ReflectionDocumentationStrategy::class) + ->addTag('ferror.asyncapi_doc_bundle.documentation-strategy') ; // Async API v2 @@ -56,10 +64,14 @@ public function load(array $configs, ContainerBuilder $container): void ->addArgument($config['version']) ; + $container + ->register(DocumentationEditor::class) + ; + $container ->register(SchemaV2Renderer::class) ->addArgument(new Reference('ferror.asyncapi_doc_bundle.class_finder.manual')) - ->addArgument(new Reference('ferror.asyncapi_doc_bundle.documentation.attributes')) + ->addArgument(new Reference(DocumentationEditor::class)) ->addArgument(new Reference(ChannelRenderer::class)) ->addArgument(new Reference(MessageRenderer::class)) ->addArgument(new Reference(InfoRenderer::class)) diff --git a/tests/Examples/PaymentExecuted.php b/tests/Examples/PaymentExecuted.php index e55661e..984c5c2 100644 --- a/tests/Examples/PaymentExecuted.php +++ b/tests/Examples/PaymentExecuted.php @@ -5,17 +5,15 @@ namespace Ferror\AsyncapiDocBundle\Tests\Examples; use Ferror\AsyncapiDocBundle\Attribute\Message; -use Ferror\AsyncapiDocBundle\Attribute\Property; -use Ferror\AsyncapiDocBundle\Schema\Format; -use Ferror\AsyncapiDocBundle\Schema\PropertyType; +/** + * This class represents an example of documenting by ReflectionStrategy + */ #[Message(name: 'PaymentExecuted', channel: 'payment_executed')] final readonly class PaymentExecuted { public function __construct( - #[Property(name: 'amount', type: PropertyType::FLOAT, description: 'Payment amount', format: Format::FLOAT, example: '1000')] public float $amount, - #[Property(name: 'createdAt', type: PropertyType::STRING, description: 'Creation date', format: Format::DATETIME, example: '2023-11-23 13:41:21')] public string $createdAt, ) { } diff --git a/tests/Examples/ProductCreated.php b/tests/Examples/ProductCreated.php index abedbd4..74e5e84 100644 --- a/tests/Examples/ProductCreated.php +++ b/tests/Examples/ProductCreated.php @@ -14,6 +14,9 @@ use Ferror\AsyncapiDocBundle\Schema\Format; use Ferror\AsyncapiDocBundle\Schema\PropertyType; +/** + * This class represents an example of documenting by AttributeStrategy. It contains all types. + */ #[Message(name: 'ProductCreated', channel: 'product.created')] final readonly class ProductCreated { diff --git a/tests/Examples/ProductUpdated.php b/tests/Examples/ProductUpdated.php index cc5e6d7..7553f34 100644 --- a/tests/Examples/ProductUpdated.php +++ b/tests/Examples/ProductUpdated.php @@ -14,6 +14,9 @@ use Ferror\AsyncapiDocBundle\Schema\Format; use Ferror\AsyncapiDocBundle\Schema\PropertyType; +/** + * This class represents an example of documenting by AttributeStrategy. The properties are provided via objects. + */ #[Message( name: 'ProductUpdated', channel: 'product.updated', diff --git a/tests/Examples/UserSignedUp.php b/tests/Examples/UserSignedUp.php index 0fb4c10..0854989 100644 --- a/tests/Examples/UserSignedUp.php +++ b/tests/Examples/UserSignedUp.php @@ -9,6 +9,9 @@ use Ferror\AsyncapiDocBundle\Schema\Format; use Ferror\AsyncapiDocBundle\Schema\PropertyType; +/** + * This class represents a SIMPLE example of documenting by AttributeStrategy. + */ #[Message(name: 'UserSignedUp', channel: 'user_signed_up')] final readonly class UserSignedUp { diff --git a/tests/Integration/DumpSpecificationConsoleTest.php b/tests/Integration/DumpSpecificationConsoleTest.php index 130d3d9..2450c8f 100644 --- a/tests/Integration/DumpSpecificationConsoleTest.php +++ b/tests/Integration/DumpSpecificationConsoleTest.php @@ -140,14 +140,8 @@ public function testExecuteYaml(): void properties: amount: type: number - description: 'Payment amount' - format: float - example: '1000' createdAt: type: string - description: 'Creation date' - format: date-time - example: '2023-11-23 13:41:21' required: - amount - createdAt @@ -157,32 +151,23 @@ public function testExecuteYaml(): void properties: id: type: integer - description: '' amount: type: number - description: '' currency: type: string - description: '' isPaid: type: boolean - description: '' createdAt: type: string - description: '' format: date-time week: type: integer - description: '' payment: type: string - description: '' products: type: string - description: '' tags: type: string - description: '' required: - id - amount @@ -293,12 +278,12 @@ public function testExecuteJson(): void "example": "true" } }, - "required": [ - "name", - "email", - "age", - "isCitizen" - ] + "required": [ + "name", + "email", + "age", + "isCitizen" + ] } }, "PaymentExecuted": { @@ -306,22 +291,16 @@ public function testExecuteJson(): void "type": "object", "properties": { "amount": { - "type": "number", - "description": "Payment amount", - "format": "float", - "example": "1000" + "type": "number" }, "createdAt": { - "type": "string", - "description": "Creation date", - "format": "date-time", - "example": "2023-11-23 13:41:21" + "type": "string" } }, - "required": [ - "amount", - "createdAt" - ] + "required": [ + "amount", + "createdAt" + ] } }, "ProductCreated": { @@ -329,54 +308,45 @@ public function testExecuteJson(): void "type": "object", "properties": { "id": { - "type": "integer", - "description": "" + "type": "integer" }, "amount": { - "type": "number", - "description": "" + "type": "number" }, "currency": { - "type": "string", - "description": "" + "type": "string" }, "isPaid": { - "type": "boolean", - "description": "" + "type": "boolean" }, "createdAt": { "type": "string", - "description": "", "format": "date-time" }, "week": { - "type": "integer", - "description": "" + "type": "integer" }, "payment": { - "type": "string", - "description": "" + "type": "string" }, "products": { - "type": "string", - "description": "" + "type": "string" }, "tags": { - "type": "string", - "description": "" + "type": "string" } }, - "required": [ - "id", - "amount", - "currency", - "isPaid", - "createdAt", - "week", - "payment", - "products", - "tags" - ] + "required": [ + "id", + "amount", + "currency", + "isPaid", + "createdAt", + "week", + "payment", + "products", + "tags" + ] } } } diff --git a/tests/Integration/UserInterfaceControllerTest.php b/tests/Integration/UserInterfaceControllerTest.php index 3494146..b7c28ef 100644 --- a/tests/Integration/UserInterfaceControllerTest.php +++ b/tests/Integration/UserInterfaceControllerTest.php @@ -7,6 +7,7 @@ use Ferror\AsyncapiDocBundle\Tests\Integration\Service\Kernel; use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\KernelBrowser; +use Symfony\Component\HttpFoundation\Request; class UserInterfaceControllerTest extends TestCase { @@ -14,7 +15,7 @@ public function test(): void { $client = new KernelBrowser(new Kernel('test', true)); - $client->request('GET', '/asyncapi'); + $client->request(Request::METHOD_GET, '/asyncapi'); $this->assertEquals(200, $client->getResponse()->getStatusCode()); } diff --git a/tests/Unit/Attribute/MessageTest.php b/tests/Unit/Attribute/MessageTest.php new file mode 100644 index 0000000..fa48eea --- /dev/null +++ b/tests/Unit/Attribute/MessageTest.php @@ -0,0 +1,30 @@ +enrich(new Message('name', 'channel', [new Property('name')])); + + $this->assertCount(1, $message->properties); + } + + public function testEnrichUpdatesProperty(): void + { + $message = new Message('name', 'channel', [new Property('name')]); + + $message->enrich(new Message('name', 'channel', [new Property('name', 'Nice Description')])); + + $this->assertEquals('Nice Description', $message->properties[0]->description); + } +} diff --git a/tests/Unit/DocumentationEditorTest.php b/tests/Unit/DocumentationEditorTest.php new file mode 100644 index 0000000..cb46f87 --- /dev/null +++ b/tests/Unit/DocumentationEditorTest.php @@ -0,0 +1,51 @@ +document(PaymentExecuted::class)->toArray(); + + $expected = [ + 'name' => 'PaymentExecuted', + 'channel' => 'payment_executed', + 'channelType' => 'subscribe', + 'properties' => [ + [ + 'name' => 'amount', + 'required' => true, + 'type' => 'number', + 'description' => '', + 'format' => null, + 'example' => null, + ], + [ + 'name' => 'createdAt', + 'description' => '', + 'required' => true, + 'type' => 'string', + 'format' => null, + 'example' => null, + ], + ], + ]; + + $this->assertEquals($expected, $actual); + } +} diff --git a/tests/Unit/DocumentationStrategy/AttributeDocumentationStrategyTest.php b/tests/Unit/DocumentationStrategy/AttributeDocumentationStrategyTest.php index 8fe18ec..5c3d689 100644 --- a/tests/Unit/DocumentationStrategy/AttributeDocumentationStrategyTest.php +++ b/tests/Unit/DocumentationStrategy/AttributeDocumentationStrategyTest.php @@ -16,6 +16,8 @@ public function testUserSignedUp(): void { $documentation = new AttributeDocumentationStrategy(new PropertyExtractor()); + $actual = $documentation->document(UserSignedUp::class)->toArray(); + $expected = [ 'name' => 'UserSignedUp', 'channel' => 'user_signed_up', @@ -56,13 +58,15 @@ public function testUserSignedUp(): void ], ]; - $this->assertEquals($expected, $documentation->document(UserSignedUp::class)); + $this->assertEquals($expected, $actual); } public function testProductCreated(): void { $documentation = new AttributeDocumentationStrategy(new PropertyExtractor()); + $actual = $documentation->document(ProductCreated::class)->toArray(); + $expected = [ 'name' => 'ProductCreated', 'channel' => 'product.created', @@ -144,6 +148,6 @@ public function testProductCreated(): void ], ]; - $this->assertEquals($expected, $documentation->document(ProductCreated::class)); + $this->assertEquals($expected, $actual); } } diff --git a/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php b/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php index 53359eb..29abcc5 100644 --- a/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php +++ b/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php @@ -5,6 +5,7 @@ namespace Ferror\AsyncapiDocBundle\Tests\Unit\DocumentationStrategy; use Ferror\AsyncapiDocBundle\DocumentationStrategy\ReflectionDocumentationStrategy; +use Ferror\AsyncapiDocBundle\Tests\Examples\ProductCreated; use Ferror\AsyncapiDocBundle\Tests\Examples\UserSignedUp; use PHPUnit\Framework\TestCase; @@ -16,32 +17,94 @@ public function test(): void $expected = [ 'name' => 'UserSignedUp', + 'channel' => 'user_signed_up', + 'channelType' => 'subscribe', 'properties' => [ [ 'name' => 'name', 'type' => 'string', + 'required' => true, + 'description' => '', + 'format' => null, + 'example' => null, ], [ 'name' => 'email', 'type' => 'string', + 'required' => true, + 'description' => '', + 'format' => null, + 'example' => null, ], [ 'name' => 'age', - 'type' => 'int', + 'type' => 'integer', + 'required' => true, + 'description' => '', + 'format' => null, + 'example' => null, ], [ 'name' => 'isCitizen', - 'type' => 'bool', + 'type' => 'boolean', + 'required' => true, + 'description' => '', + 'format' => null, + 'example' => null, ], ], - 'required' => [ - 'name', - 'email', - 'age', - 'isCitizen', - ] ]; - $this->assertEquals($expected, $documentation->document(UserSignedUp::class)); + $this->assertEquals($expected, $documentation->document(UserSignedUp::class)->toArray()); + } + + public function testEnum(): void + { + $documentation = new ReflectionDocumentationStrategy(); + + $expected = [ + 'name' => 'ProductCreated', + 'channel' => 'product.created', + 'channelType' => 'subscribe', + 'properties' => [ + [ + 'name' => 'id', + 'description' => '', + 'required' => true, + 'type' => 'integer', + 'format' => null, + 'example' => null + ], + [ + 'name' => 'amount', + 'description' => '', + 'required' => true, + 'type' => 'number', + 'format' => null, + 'example' => null + ], + [ + 'name' => 'currency', + 'description' => '', + 'required' => true, + 'type' => 'string', + 'format' => null, + 'example' => null + ], + [ + 'name' => 'isPaid', + 'description' => '', + 'required' => true, + 'type' => 'boolean', + 'format' => null, + 'example' => null + ], + ], + ]; + + + $actual = $documentation->document(ProductCreated::class)->toArray(); + + $this->assertEquals($expected, $actual); } } diff --git a/tests/Unit/Schema/V2/MessageRendererTest.php b/tests/Unit/Schema/V2/MessageRendererTest.php index b74ff0c..53dccb9 100644 --- a/tests/Unit/Schema/V2/MessageRendererTest.php +++ b/tests/Unit/Schema/V2/MessageRendererTest.php @@ -145,4 +145,50 @@ public function testAttributes(): void $this->assertEquals($expectedSpecification, Yaml::dump($specification, 10, 2)); } + + public function testDoesNotRenderEmptyData(): void + { + $document = [ + 'name' => 'UserSignedUp', + 'properties' => [ + [ + 'name' => 'firstName', + 'type' => 'string', + 'description' => '', + 'example' => '', + 'format' => null, + ], + [ + 'name' => 'secondName', + 'type' => 'string', + 'description' => '', + 'example' => '', + 'format' => '', + ], + ], + ]; + + $schema = new MessageRenderer(); + + $actual = $schema->render($document); + + $expected = [ + 'UserSignedUp' => [ + 'payload' => [ + 'type' => 'object', + 'properties' => [ + 'firstName' => [ + 'type' => 'string', + ], + 'secondName' => [ + 'type' => 'string', + ], + ], + 'required' => [], + ], + ], + ]; + + $this->assertEquals($expected, $actual); + } } diff --git a/tests/Unit/Symfony/Controller/JsonSpecificationControllerTest.php b/tests/Unit/Symfony/Controller/JsonSpecificationControllerTest.php index 3cd3816..d8807e4 100644 --- a/tests/Unit/Symfony/Controller/JsonSpecificationControllerTest.php +++ b/tests/Unit/Symfony/Controller/JsonSpecificationControllerTest.php @@ -5,8 +5,10 @@ namespace Ferror\AsyncapiDocBundle\Tests\Unit\Symfony\Controller; use Ferror\AsyncapiDocBundle\ClassFinder\ManualClassFinder; +use Ferror\AsyncapiDocBundle\DocumentationEditor; use Ferror\AsyncapiDocBundle\DocumentationStrategy\AttributeDocumentationStrategy; use Ferror\AsyncapiDocBundle\DocumentationStrategy\PropertyExtractor; +use Ferror\AsyncapiDocBundle\DocumentationStrategy\ReflectionDocumentationStrategy; use Ferror\AsyncapiDocBundle\Generator\JsonGenerator; use Ferror\AsyncapiDocBundle\Schema\V2\ChannelRenderer; use Ferror\AsyncapiDocBundle\Schema\V2\InfoRenderer; @@ -30,7 +32,10 @@ public function test(): void PaymentExecuted::class, ProductCreated::class, ]), - new AttributeDocumentationStrategy(new PropertyExtractor()), + new DocumentationEditor([ + new AttributeDocumentationStrategy(new PropertyExtractor()), + new ReflectionDocumentationStrategy(), + ]), new ChannelRenderer(), new MessageRenderer(), new InfoRenderer('Service Example API', 'This service is in charge of processing user signups', '1.2.3'), @@ -103,12 +108,12 @@ public function test(): void "example": "true" } }, - "required": [ - "name", - "email", - "age", - "isCitizen" - ] + "required": [ + "name", + "email", + "age", + "isCitizen" + ] } }, "PaymentExecuted": { @@ -116,22 +121,16 @@ public function test(): void "type": "object", "properties": { "amount": { - "type": "number", - "description": "Payment amount", - "format": "float", - "example": "1000" + "type": "number" }, "createdAt": { - "type": "string", - "description": "Creation date", - "format": "date-time", - "example": "2023-11-23 13:41:21" + "type": "string" } }, - "required": [ - "amount", - "createdAt" - ] + "required": [ + "amount", + "createdAt" + ] } }, "ProductCreated": { @@ -139,54 +138,45 @@ public function test(): void "type": "object", "properties": { "id": { - "type": "integer", - "description": "" + "type": "integer" }, "amount": { - "type": "number", - "description": "" + "type": "number" }, "currency": { - "type": "string", - "description": "" + "type": "string" }, "isPaid": { - "type": "boolean", - "description": "" + "type": "boolean" }, "createdAt": { "type": "string", - "description": "", "format": "date-time" }, "week": { - "type": "integer", - "description": "" + "type": "integer" }, "payment": { - "type": "string", - "description": "" + "type": "string" }, "products": { - "type": "string", - "description": "" + "type": "string" }, "tags": { - "type": "string", - "description": "" + "type": "string" } }, - "required": [ - "id", - "amount", - "currency", - "isPaid", - "createdAt", - "week", - "payment", - "products", - "tags" - ] + "required": [ + "id", + "amount", + "currency", + "isPaid", + "createdAt", + "week", + "payment", + "products", + "tags" + ] } } } diff --git a/tests/Unit/Symfony/Controller/YamlSpecificationControllerTest.php b/tests/Unit/Symfony/Controller/YamlSpecificationControllerTest.php index 1a4b9b1..d8912f3 100644 --- a/tests/Unit/Symfony/Controller/YamlSpecificationControllerTest.php +++ b/tests/Unit/Symfony/Controller/YamlSpecificationControllerTest.php @@ -5,8 +5,10 @@ namespace Ferror\AsyncapiDocBundle\Tests\Unit\Symfony\Controller; use Ferror\AsyncapiDocBundle\ClassFinder\ManualClassFinder; +use Ferror\AsyncapiDocBundle\DocumentationEditor; use Ferror\AsyncapiDocBundle\DocumentationStrategy\AttributeDocumentationStrategy; use Ferror\AsyncapiDocBundle\DocumentationStrategy\PropertyExtractor; +use Ferror\AsyncapiDocBundle\DocumentationStrategy\ReflectionDocumentationStrategy; use Ferror\AsyncapiDocBundle\Generator\YamlGenerator; use Ferror\AsyncapiDocBundle\Schema\V2\ChannelRenderer; use Ferror\AsyncapiDocBundle\Schema\V2\InfoRenderer; @@ -30,7 +32,10 @@ public function test(): void PaymentExecuted::class, ProductCreated::class, ]), - new AttributeDocumentationStrategy(new PropertyExtractor()), + new DocumentationEditor([ + new AttributeDocumentationStrategy(new PropertyExtractor()), + new ReflectionDocumentationStrategy(), + ]), new ChannelRenderer(), new MessageRenderer(), new InfoRenderer('Service Example API', 'This service is in charge of processing user signups', '1.2.3'), @@ -97,14 +102,8 @@ public function test(): void properties: amount: type: number - description: 'Payment amount' - format: float - example: '1000' createdAt: type: string - description: 'Creation date' - format: date-time - example: '2023-11-23 13:41:21' required: - amount - createdAt @@ -114,32 +113,23 @@ public function test(): void properties: id: type: integer - description: '' amount: type: number - description: '' currency: type: string - description: '' isPaid: type: boolean - description: '' createdAt: type: string - description: '' format: date-time week: type: integer - description: '' payment: type: string - description: '' products: type: string - description: '' tags: type: string - description: '' required: - id - amount