diff --git a/composer.json b/composer.json index edc48bc3..0665d3b4 100644 --- a/composer.json +++ b/composer.json @@ -19,8 +19,8 @@ ], "require": { "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "patchlevel/event-sourcing": "^3.19.1", - "patchlevel/hydrator": "^1.21.2", + "patchlevel/event-sourcing": "^3.22.1", + "patchlevel/hydrator": "^1.24.3", "symfony/cache": "^6.4.0 || ^7.0.0 || ^8.0.0", "symfony/config": "^6.4.0 || ^7.0.0 || ^8.0.0", "symfony/console": "^6.4.1 || ^7.0.1 || ^8.0.0", diff --git a/composer.lock b/composer.lock index 5cd99b75..128e2ad6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,28 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0e3fa28fe7ed5a005faf5d26aaae1ca2", + "content-hash": "f76b6fb6afcec78aa85dbb341efcc964", "packages": [ { "name": "brick/math", - "version": "0.18.0", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "82944324d1c1bdb2c2618e89978d4e2ad78d69ad" + "reference": "2effe05d2177c451b86c6a073196a4034c02f211" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/82944324d1c1bdb2c2618e89978d4e2ad78d69ad", - "reference": "82944324d1c1bdb2c2618e89978d4e2ad78d69ad", + "url": "https://api.github.com/repos/brick/math/zipball/2effe05d2177c451b86c6a073196a4034c02f211", + "reference": "2effe05d2177c451b86c6a073196a4034c02f211", "shasum": "" }, "require": { "php": "^8.2" }, "require-dev": { - "phpstan/phpstan": "2.1.22", + "phpstan/phpstan": "2.2.13", + "phpstan/phpstan-phpunit": "2.0.18", "phpunit/phpunit": "^11.5" }, "type": "library", @@ -55,7 +56,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.18.0" + "source": "https://github.com/brick/math/tree/1.0.0" }, "funding": [ { @@ -63,20 +64,20 @@ "type": "github" } ], - "time": "2026-06-14T18:21:03+00:00" + "time": "2026-09-12T10:28:18+00:00" }, { "name": "doctrine/dbal", - "version": "4.4.4", + "version": "4.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "fb9e0ffe15e1590e24dc61c0c0a23f9a33ee42ce" + "reference": "c435cd7ea33e17d2a89288caf994cf3d4549b879" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/fb9e0ffe15e1590e24dc61c0c0a23f9a33ee42ce", - "reference": "fb9e0ffe15e1590e24dc61c0c0a23f9a33ee42ce", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/c435cd7ea33e17d2a89288caf994cf3d4549b879", + "reference": "c435cd7ea33e17d2a89288caf994cf3d4549b879", "shasum": "" }, "require": { @@ -92,9 +93,9 @@ "phpstan/phpstan": "2.1.30", "phpstan/phpstan-phpunit": "2.0.7", "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "11.5.50", - "slevomat/coding-standard": "8.27.1", - "squizlabs/php_codesniffer": "4.0.1", + "phpunit/phpunit": "11.5.56", + "slevomat/coding-standard": "8.31.1", + "squizlabs/php_codesniffer": "4.0.4", "symfony/cache": "^6.3.8|^7.0|^8.0", "symfony/console": "^5.4|^6.3|^7.0|^8.0" }, @@ -153,7 +154,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.4.4" + "source": "https://github.com/doctrine/dbal/tree/4.5.0" }, "funding": [ { @@ -169,7 +170,7 @@ "type": "tidelift" } ], - "time": "2026-07-21T14:34:40+00:00" + "time": "2026-09-24T16:11:26+00:00" }, { "name": "doctrine/deprecations", @@ -312,16 +313,16 @@ }, { "name": "doctrine/migrations", - "version": "3.9.7", + "version": "3.9.8", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "96cb2a89b56c9efb0bac38e606dc0b0f13e650ec" + "reference": "eb0b9ce3f999d720fa73037bbd06977ea34b76a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/96cb2a89b56c9efb0bac38e606dc0b0f13e650ec", - "reference": "96cb2a89b56c9efb0bac38e606dc0b0f13e650ec", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/eb0b9ce3f999d720fa73037bbd06977ea34b76a0", + "reference": "eb0b9ce3f999d720fa73037bbd06977ea34b76a0", "shasum": "" }, "require": { @@ -395,7 +396,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.9.7" + "source": "https://github.com/doctrine/migrations/tree/3.9.8" }, "funding": [ { @@ -411,20 +412,20 @@ "type": "tidelift" } ], - "time": "2026-04-23T19:33:20+00:00" + "time": "2026-10-04T12:35:58+00:00" }, { "name": "patchlevel/event-sourcing", - "version": "3.21.0", + "version": "3.22.1", "source": { "type": "git", "url": "https://github.com/patchlevel/event-sourcing.git", - "reference": "95cd2a4a07564774569698e3be141dd814160164" + "reference": "809e5641b1d2caf575fbddc5d0a988055af0aaf1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/patchlevel/event-sourcing/zipball/95cd2a4a07564774569698e3be141dd814160164", - "reference": "95cd2a4a07564774569698e3be141dd814160164", + "url": "https://api.github.com/repos/patchlevel/event-sourcing/zipball/809e5641b1d2caf575fbddc5d0a988055af0aaf1", + "reference": "809e5641b1d2caf575fbddc5d0a988055af0aaf1", "shasum": "" }, "require": { @@ -455,6 +456,7 @@ "phpstan/phpstan": "^2.1.11", "phpstan/phpstan-phpunit": "^2.0", "phpunit/phpunit": "^11.5.15", + "symfony/cache": "^6.4.0 || ^7.0.0 || ^8.0.0", "symfony/messenger": "^5.4.31 || ^6.4.0 || ^7.0.1 || ^8.0.0", "symfony/var-dumper": "^5.4.29 || ^6.4.0 || ^7.0.0 || ^8.0.0", "wnx/commonmark-markdown-renderer": "^1.5.0" @@ -502,22 +504,22 @@ ], "support": { "issues": "https://github.com/patchlevel/event-sourcing/issues", - "source": "https://github.com/patchlevel/event-sourcing/tree/3.21.0" + "source": "https://github.com/patchlevel/event-sourcing/tree/3.22.1" }, - "time": "2026-08-26T11:46:16+00:00" + "time": "2026-10-07T10:28:14+00:00" }, { "name": "patchlevel/hydrator", - "version": "1.24.1", + "version": "1.24.3", "source": { "type": "git", "url": "https://github.com/patchlevel/hydrator.git", - "reference": "3e12685569c2f18b8a16eae8a14467a002063799" + "reference": "b0c79d2b80ccf0ab95cc9b4494105af6b6bf00de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/patchlevel/hydrator/zipball/3e12685569c2f18b8a16eae8a14467a002063799", - "reference": "3e12685569c2f18b8a16eae8a14467a002063799", + "url": "https://api.github.com/repos/patchlevel/hydrator/zipball/b0c79d2b80ccf0ab95cc9b4494105af6b6bf00de", + "reference": "b0c79d2b80ccf0ab95cc9b4494105af6b6bf00de", "shasum": "" }, "require": { @@ -536,6 +538,7 @@ "phpstan/phpstan": "^2.1.39", "phpstan/phpstan-phpunit": "^2.0.15", "phpunit/phpunit": "^11.5.53", + "symfony/cache": "^6.4.0 || ^7.0.0 || ^8.0.0", "symfony/var-dumper": "^5.4.29 || ^6.4.0 || ^7.0.0 || ^8.0.0" }, "type": "library", @@ -566,37 +569,43 @@ ], "support": { "issues": "https://github.com/patchlevel/hydrator/issues", - "source": "https://github.com/patchlevel/hydrator/tree/1.24.1" + "source": "https://github.com/patchlevel/hydrator/tree/1.24.3" }, - "time": "2026-09-01T07:45:47+00:00" + "time": "2026-10-07T10:27:41+00:00" }, { "name": "patchlevel/worker", - "version": "1.5.0", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/patchlevel/worker.git", - "reference": "0288d740de7d9806d8dc9dd4c2545be31a043823" + "reference": "100b0b2b960c8cd32a6e5a717777d56d81791425" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/patchlevel/worker/zipball/0288d740de7d9806d8dc9dd4c2545be31a043823", - "reference": "0288d740de7d9806d8dc9dd4c2545be31a043823", + "url": "https://api.github.com/repos/patchlevel/worker/zipball/100b0b2b960c8cd32a6e5a717777d56d81791425", + "reference": "100b0b2b960c8cd32a6e5a717777d56d81791425", "shasum": "" }, "require": { "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "psr/clock": "^1.0", + "psr/log": "^1.1 || ^2.0 || ^3.0", "symfony/event-dispatcher": "^5.4.26 || ^6.4.0 || ^7.0.0 || ^8.0.0" }, "require-dev": { - "infection/infection": "^0.31.9", + "infection/infection": "^0.32.0", "patchlevel/coding-standard": "^1.3.0", "phpat/phpat": "^0.12.0", "phpbench/phpbench": "^1.2.15", "phpstan/phpstan": "^2.1.32", "phpstan/phpstan-phpunit": "^2.0.8", "phpunit/phpunit": "^11.5.3", - "symfony/var-dumper": "^5.4.29 || ^6.4.0 || ^7.0.0 || ^8.0.0" + "symfony/var-dumper": "^5.4.29 || ^6.4.0 || ^7.0.0 || ^8.0.0", + "wnx/commonmark-markdown-renderer": "^1.6" + }, + "suggest": { + "ext-pcntl": "Required to stop the worker gracefully on SIGTERM" }, "type": "library", "autoload": { @@ -626,9 +635,9 @@ ], "support": { "issues": "https://github.com/patchlevel/worker/issues", - "source": "https://github.com/patchlevel/worker/tree/1.5.0" + "source": "https://github.com/patchlevel/worker/tree/1.7.0" }, - "time": "2025-11-27T15:33:31+00:00" + "time": "2026-10-05T07:23:26+00:00" }, { "name": "psr/cache", @@ -1009,20 +1018,20 @@ }, { "name": "ramsey/uuid", - "version": "4.9.3", + "version": "4.9.4", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "1df15849d00943a67d677dc9cfd80795f038c9f8" + "reference": "75d73f48d02797c2c285a7e9f348fadc0102ffe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/1df15849d00943a67d677dc9cfd80795f038c9f8", - "reference": "1df15849d00943a67d677dc9cfd80795f038c9f8", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/75d73f48d02797c2c285a7e9f348fadc0102ffe2", + "reference": "75d73f48d02797c2c285a7e9f348fadc0102ffe2", "shasum": "" }, "require": { - "brick/math": ">=0.8.16 <=0.18", + "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14 || ^0.15 || ^0.16 || ^0.17 || ^0.18 || ^0.19 || ^0.20 || ^1.0", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" }, @@ -1081,22 +1090,22 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.9.3" + "source": "https://github.com/ramsey/uuid/tree/4.9.4" }, - "time": "2026-06-18T03:57:49+00:00" + "time": "2026-09-16T11:39:30+00:00" }, { "name": "symfony/cache", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "47616ab077b5aff4d0f718b96680a48599fc1a3f" + "reference": "8888daf06a2fc8440346215d3b52f3c611cc486d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/47616ab077b5aff4d0f718b96680a48599fc1a3f", - "reference": "47616ab077b5aff4d0f718b96680a48599fc1a3f", + "url": "https://api.github.com/repos/symfony/cache/zipball/8888daf06a2fc8440346215d3b52f3c611cc486d", + "reference": "8888daf06a2fc8440346215d3b52f3c611cc486d", "shasum": "" }, "require": { @@ -1162,7 +1171,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v8.1.7" + "source": "https://github.com/symfony/cache/tree/v8.1.8" }, "funding": [ { @@ -1182,7 +1191,7 @@ "type": "tidelift" } ], - "time": "2026-09-08T13:39:13+00:00" + "time": "2026-09-29T12:38:40+00:00" }, { "name": "symfony/cache-contracts", @@ -1421,16 +1430,16 @@ }, { "name": "symfony/console", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "29afb89f4e941f68a6e90f28e3f52ff1f6793a7d" + "reference": "4b81146e3ee248ea969186f85499b54fbc78db08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/29afb89f4e941f68a6e90f28e3f52ff1f6793a7d", - "reference": "29afb89f4e941f68a6e90f28e3f52ff1f6793a7d", + "url": "https://api.github.com/repos/symfony/console/zipball/4b81146e3ee248ea969186f85499b54fbc78db08", + "reference": "4b81146e3ee248ea969186f85499b54fbc78db08", "shasum": "" }, "require": { @@ -1497,7 +1506,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v8.1.7" + "source": "https://github.com/symfony/console/tree/v8.1.8" }, "funding": [ { @@ -1517,20 +1526,20 @@ "type": "tidelift" } ], - "time": "2026-09-13T10:55:57+00:00" + "time": "2026-09-18T16:00:27+00:00" }, { "name": "symfony/dependency-injection", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "3fd96e4b54e2372c4ce019cee9d5026add6e7f38" + "reference": "e375617d3f132059bd096f41951b527c2eb60cd0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/3fd96e4b54e2372c4ce019cee9d5026add6e7f38", - "reference": "3fd96e4b54e2372c4ce019cee9d5026add6e7f38", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e375617d3f132059bd096f41951b527c2eb60cd0", + "reference": "e375617d3f132059bd096f41951b527c2eb60cd0", "shasum": "" }, "require": { @@ -1578,7 +1587,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/v8.1.7" + "source": "https://github.com/symfony/dependency-injection/tree/v8.1.8" }, "funding": [ { @@ -1598,7 +1607,7 @@ "type": "tidelift" } ], - "time": "2026-09-11T15:21:30+00:00" + "time": "2026-09-29T12:38:40+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1673,16 +1682,16 @@ }, { "name": "symfony/error-handler", - "version": "v8.1.5", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce" + "reference": "c146daceccd5d4f864c051b233c276641cec527b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce", - "reference": "8b2a4289ffe5e2dc8fcf645b8e7870e1fa0325ce", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/c146daceccd5d4f864c051b233c276641cec527b", + "reference": "c146daceccd5d4f864c051b233c276641cec527b", "shasum": "" }, "require": { @@ -1730,7 +1739,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/v8.1.5" + "source": "https://github.com/symfony/error-handler/tree/v8.1.8" }, "funding": [ { @@ -1750,7 +1759,7 @@ "type": "tidelift" } ], - "time": "2026-08-21T17:47:34+00:00" + "time": "2026-09-22T18:58:53+00:00" }, { "name": "symfony/event-dispatcher", @@ -1991,16 +2000,16 @@ }, { "name": "symfony/finder", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "4fbe46a3eb64abf8a57f0364075b91f4a233e062" + "reference": "bd4fed193a3132c91c5c93595cbfc78988915822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/4fbe46a3eb64abf8a57f0364075b91f4a233e062", - "reference": "4fbe46a3eb64abf8a57f0364075b91f4a233e062", + "url": "https://api.github.com/repos/symfony/finder/zipball/bd4fed193a3132c91c5c93595cbfc78988915822", + "reference": "bd4fed193a3132c91c5c93595cbfc78988915822", "shasum": "" }, "require": { @@ -2035,7 +2044,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v8.1.7" + "source": "https://github.com/symfony/finder/tree/v8.1.8" }, "funding": [ { @@ -2055,20 +2064,20 @@ "type": "tidelift" } ], - "time": "2026-09-10T19:14:39+00:00" + "time": "2026-09-26T06:33:49+00:00" }, { "name": "symfony/http-foundation", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "d8fdc670ed510a69e3a9eb4f5eac89f5ed627e17" + "reference": "662f5257658d4f60deff1bc790e9f2c68cb391bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/d8fdc670ed510a69e3a9eb4f5eac89f5ed627e17", - "reference": "d8fdc670ed510a69e3a9eb4f5eac89f5ed627e17", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/662f5257658d4f60deff1bc790e9f2c68cb391bf", + "reference": "662f5257658d4f60deff1bc790e9f2c68cb391bf", "shasum": "" }, "require": { @@ -2116,7 +2125,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v8.1.7" + "source": "https://github.com/symfony/http-foundation/tree/v8.1.8" }, "funding": [ { @@ -2136,20 +2145,20 @@ "type": "tidelift" } ], - "time": "2026-09-14T17:47:24+00:00" + "time": "2026-09-24T07:13:53+00:00" }, { "name": "symfony/http-kernel", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "ec7a3a5832c22cf880cf27d2fdc7ad2e94838e85" + "reference": "51c014e881d8b4ce61e56c0d4105f65b50df786a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ec7a3a5832c22cf880cf27d2fdc7ad2e94838e85", - "reference": "ec7a3a5832c22cf880cf27d2fdc7ad2e94838e85", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/51c014e881d8b4ce61e56c0d4105f65b50df786a", + "reference": "51c014e881d8b4ce61e56c0d4105f65b50df786a", "shasum": "" }, "require": { @@ -2226,7 +2235,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/v8.1.7" + "source": "https://github.com/symfony/http-kernel/tree/v8.1.8" }, "funding": [ { @@ -2246,20 +2255,20 @@ "type": "tidelift" } ], - "time": "2026-09-15T07:12:52+00:00" + "time": "2026-09-29T14:08:01+00:00" }, { "name": "symfony/messenger", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/messenger.git", - "reference": "90019bfcb5c2c3d9e44a18186e2381c261be1717" + "reference": "01b42daaefd1e020fabf2e94cf9448b1f2ad6f98" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/messenger/zipball/90019bfcb5c2c3d9e44a18186e2381c261be1717", - "reference": "90019bfcb5c2c3d9e44a18186e2381c261be1717", + "url": "https://api.github.com/repos/symfony/messenger/zipball/01b42daaefd1e020fabf2e94cf9448b1f2ad6f98", + "reference": "01b42daaefd1e020fabf2e94cf9448b1f2ad6f98", "shasum": "" }, "require": { @@ -2318,7 +2327,7 @@ "description": "Helps applications send and receive messages to/from other applications or via message queues", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/messenger/tree/v8.1.7" + "source": "https://github.com/symfony/messenger/tree/v8.1.8" }, "funding": [ { @@ -2338,7 +2347,7 @@ "type": "tidelift" } ], - "time": "2026-09-14T17:47:24+00:00" + "time": "2026-09-29T12:38:40+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2425,16 +2434,16 @@ }, { "name": "symfony/polyfill-deepclone", - "version": "v1.42.0", + "version": "v1.43.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-deepclone.git", - "reference": "70ba0627efc68e97ea392843458a2dd9d6dbd156" + "reference": "aaba44b6ee7299ae65717811c55b57ab9bc0fedd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-deepclone/zipball/70ba0627efc68e97ea392843458a2dd9d6dbd156", - "reference": "70ba0627efc68e97ea392843458a2dd9d6dbd156", + "url": "https://api.github.com/repos/symfony/polyfill-deepclone/zipball/aaba44b6ee7299ae65717811c55b57ab9bc0fedd", + "reference": "aaba44b6ee7299ae65717811c55b57ab9bc0fedd", "shasum": "" }, "require": { @@ -2488,7 +2497,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-deepclone/tree/v1.42.0" + "source": "https://github.com/symfony/polyfill-deepclone/tree/v1.43.1" }, "funding": [ { @@ -2508,20 +2517,20 @@ "type": "tidelift" } ], - "time": "2026-08-07T06:33:24+00:00" + "time": "2026-10-06T19:46:18+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d" + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", - "reference": "bb899c1db0aa8127dc3afe8cda4a67eb24915f8d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5cac8f4db97208823aa353f59a01faad2da52c75", + "reference": "5cac8f4db97208823aa353f59a01faad2da52c75", "shasum": "" }, "require": { @@ -2570,7 +2579,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.43.0" }, "funding": [ { @@ -2590,20 +2599,20 @@ "type": "tidelift" } ], - "time": "2026-07-28T08:25:59+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.42.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502" + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/aa20edea75bd9c48cfecc8360922e5a6e5c44502", - "reference": "aa20edea75bd9c48cfecc8360922e5a6e5c44502", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/ebd57ccc7edb93d632e184efbe7693d2517bab3b", + "reference": "ebd57ccc7edb93d632e184efbe7693d2517bab3b", "shasum": "" }, "require": { @@ -2655,7 +2664,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.42.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.43.0" }, "funding": [ { @@ -2675,20 +2684,20 @@ "type": "tidelift" } ], - "time": "2026-08-07T06:33:24+00:00" + "time": "2026-09-23T22:02:09+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.38.2", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", - "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", + "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72", "shasum": "" }, "require": { @@ -2740,7 +2749,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0" }, "funding": [ { @@ -2760,20 +2769,20 @@ "type": "tidelift" } ], - "time": "2026-05-27T06:59:30+00:00" + "time": "2026-09-24T15:19:04+00:00" }, { "name": "symfony/polyfill-php85", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php85.git", - "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a" + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/255fab485aaa1006ed411040c42aecd7b5302d7a", - "reference": "255fab485aaa1006ed411040c42aecd7b5302d7a", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/86a42cbcc07adc331481a5ab310a4024bfc227f6", + "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6", "shasum": "" }, "require": { @@ -2820,7 +2829,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php85/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.43.0" }, "funding": [ { @@ -2840,7 +2849,7 @@ "type": "tidelift" } ], - "time": "2026-07-01T12:47:55+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/service-contracts", @@ -3087,16 +3096,16 @@ }, { "name": "symfony/type-info", - "version": "v8.1.5", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/type-info.git", - "reference": "ceb48db5b38d6a48640c414be0c69d53980ae5c5" + "reference": "18e1d891f0b8776141f281f7b6f5e67e4df9d9cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/type-info/zipball/ceb48db5b38d6a48640c414be0c69d53980ae5c5", - "reference": "ceb48db5b38d6a48640c414be0c69d53980ae5c5", + "url": "https://api.github.com/repos/symfony/type-info/zipball/18e1d891f0b8776141f281f7b6f5e67e4df9d9cd", + "reference": "18e1d891f0b8776141f281f7b6f5e67e4df9d9cd", "shasum": "" }, "require": { @@ -3145,7 +3154,7 @@ "type" ], "support": { - "source": "https://github.com/symfony/type-info/tree/v8.1.5" + "source": "https://github.com/symfony/type-info/tree/v8.1.8" }, "funding": [ { @@ -3165,7 +3174,7 @@ "type": "tidelift" } ], - "time": "2026-08-21T17:47:34+00:00" + "time": "2026-09-28T19:13:15+00:00" }, { "name": "symfony/var-dumper", @@ -3987,27 +3996,25 @@ }, { "name": "doctrine/lexer", - "version": "3.0.1", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/doctrine/lexer.git", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd" + "reference": "71d305eaa6480d3d3460c7d053d1da7749fa9cca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", - "reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/71d305eaa6480d3d3460c7d053d1da7749fa9cca", + "reference": "71d305eaa6480d3d3460c7d053d1da7749fa9cca", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^5.21" + "doctrine/coding-standard": "^14", + "phpstan/phpstan": "^2", + "phpunit/phpunit": "^10.5.58 || ^12.5.4" }, "type": "library", "autoload": { @@ -4044,7 +4051,7 @@ ], "support": { "issues": "https://github.com/doctrine/lexer/issues", - "source": "https://github.com/doctrine/lexer/tree/3.0.1" + "source": "https://github.com/doctrine/lexer/tree/3.0.3" }, "funding": [ { @@ -4060,20 +4067,20 @@ "type": "tidelift" } ], - "time": "2024-02-05T11:56:58+00:00" + "time": "2026-10-01T06:59:29+00:00" }, { "name": "doctrine/orm", - "version": "3.7.1", + "version": "3.7.4", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "037807a39697890dcede8b766c5efe8a1b4855fe" + "reference": "84e21e325e3da22e46d7facbccdc9258f2332b1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/037807a39697890dcede8b766c5efe8a1b4855fe", - "reference": "037807a39697890dcede8b766c5efe8a1b4855fe", + "url": "https://api.github.com/repos/doctrine/orm/zipball/84e21e325e3da22e46d7facbccdc9258f2332b1e", + "reference": "84e21e325e3da22e46d7facbccdc9258f2332b1e", "shasum": "" }, "require": { @@ -4097,7 +4104,7 @@ "doctrine/coding-standard": "^14.0", "phpbench/phpbench": "^1.0", "phpstan/extension-installer": "^1.4", - "phpstan/phpstan": "2.1.23", + "phpstan/phpstan": "2.2.14", "phpstan/phpstan-deprecation-rules": "^2", "phpunit/phpunit": "^10.5.0 || ^11.5", "psr/log": "^1 || ^2 || ^3", @@ -4148,9 +4155,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.7.1" + "source": "https://github.com/doctrine/orm/tree/3.7.4" }, - "time": "2026-09-14T05:45:59+00:00" + "time": "2026-10-05T18:31:26+00:00" }, { "name": "doctrine/persistence", @@ -4248,23 +4255,23 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.3.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678" + "reference": "d384a7d0d6e67aa497327260ca95023e92dc2032" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", - "reference": "db9508f7b1474469d9d3c53b86f817e344732678", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/d384a7d0d6e67aa497327260ca95023e92dc2032", + "reference": "d384a7d0d6e67aa497327260ca95023e92dc2032", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "fidry/makefile": "^0.2.0", + "fidry/makefile": "^0.2.0 || ^1.1.2", "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", "phpstan/phpstan": "^2.0", @@ -4272,6 +4279,7 @@ "phpstan/phpstan-phpunit": "^2.0", "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "symfony/polyfill-mbstring": "^1.33", "webmozarts/strict-phpunit": "^7.5" }, "type": "library", @@ -4297,7 +4305,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.4.1" }, "funding": [ { @@ -4305,7 +4313,7 @@ "type": "github" } ], - "time": "2025-08-14T07:29:31+00:00" + "time": "2026-09-29T22:11:39+00:00" }, { "name": "infection/abstract-testframework-adapter", @@ -4679,16 +4687,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "6.12.0", + "version": "6.13.1", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "8ef236a1a37df364b518b7411a4b5bb95b040d79" + "reference": "e54aacc4c0657b3a4af4f628428d2702146828c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/8ef236a1a37df364b518b7411a4b5bb95b040d79", - "reference": "8ef236a1a37df364b518b7411a4b5bb95b040d79", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/e54aacc4c0657b3a4af4f628428d2702146828c6", + "reference": "e54aacc4c0657b3a4af4f628428d2702146828c6", "shasum": "" }, "require": { @@ -4738,22 +4746,22 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/6.12.0" + "source": "https://github.com/jsonrainbow/json-schema/tree/6.13.1" }, - "time": "2026-09-04T12:54:20+00:00" + "time": "2026-09-30T07:42:28+00:00" }, { "name": "league/commonmark", - "version": "2.10.2", + "version": "2.10.3", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "692e90b901877bdfd727e51270ce4394633c6e74" + "reference": "6efbd9c472b91db0a3350fcd601c8332c2382e1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/692e90b901877bdfd727e51270ce4394633c6e74", - "reference": "692e90b901877bdfd727e51270ce4394633c6e74", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/6efbd9c472b91db0a3350fcd601c8332c2382e1f", + "reference": "6efbd9c472b91db0a3350fcd601c8332c2382e1f", "shasum": "" }, "require": { @@ -4847,7 +4855,7 @@ "type": "tidelift" } ], - "time": "2026-09-21T12:28:44+00:00" + "time": "2026-09-21T13:07:34+00:00" }, { "name": "league/config", @@ -5532,16 +5540,16 @@ }, { "name": "phpstan/phpdoc-parser", - "version": "2.3.5", + "version": "2.3.6", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "148cefffaf0233e4c08cc13db8a195a56dd6dfe9" + "reference": "1427af4647235b4a73b13940b1f1258d3584f36e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/148cefffaf0233e4c08cc13db8a195a56dd6dfe9", - "reference": "148cefffaf0233e4c08cc13db8a195a56dd6dfe9", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/1427af4647235b4a73b13940b1f1258d3584f36e", + "reference": "1427af4647235b4a73b13940b1f1258d3584f36e", "shasum": "" }, "require": { @@ -5573,17 +5581,17 @@ "description": "PHPDoc parser with support for nullable, intersection and generic types", "support": { "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.5" + "source": "https://github.com/phpstan/phpdoc-parser/tree/2.3.6" }, - "time": "2026-08-31T16:05:28+00:00" + "time": "2026-09-27T20:07:45+00:00" }, { "name": "phpstan/phpstan", - "version": "2.2.14", + "version": "2.3.0", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9c672e7a8e791dfc3d30e55f683e73fc0b63a3ac", - "reference": "9c672e7a8e791dfc3d30e55f683e73fc0b63a3ac", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b1f9890d9af53a25c58129e78f0aadd31f90d7f4", + "reference": "b1f9890d9af53a25c58129e78f0aadd31f90d7f4", "shasum": "" }, "require": { @@ -5639,33 +5647,33 @@ "type": "github" } ], - "time": "2026-09-12T21:39:33+00:00" + "time": "2026-10-06T06:15:36+00:00" }, { "name": "phpstan/phpstan-symfony", - "version": "2.0.20", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-symfony.git", - "reference": "53f1a6462dbe71fad36ce054caf5e1b725b740fd" + "reference": "1981b94f0dd3a5bb42268f6a7a0e8954ac76dc2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/53f1a6462dbe71fad36ce054caf5e1b725b740fd", - "reference": "53f1a6462dbe71fad36ce054caf5e1b725b740fd", + "url": "https://api.github.com/repos/phpstan/phpstan-symfony/zipball/1981b94f0dd3a5bb42268f6a7a0e8954ac76dc2e", + "reference": "1981b94f0dd3a5bb42268f6a7a0e8954ac76dc2e", "shasum": "" }, "require": { "ext-simplexml": "*", "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.13" + "phpstan/phpstan": "^2.3" }, "conflict": { "symfony/framework-bundle": "<3.0" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan-phpunit": "^2.0.8", + "phpstan/phpstan-phpunit": "^2.0.13", "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^9.6", "psr/container": "1.1.2", @@ -5711,9 +5719,9 @@ ], "support": { "issues": "https://github.com/phpstan/phpstan-symfony/issues", - "source": "https://github.com/phpstan/phpstan-symfony/tree/2.0.20" + "source": "https://github.com/phpstan/phpstan-symfony/tree/2.1.0" }, - "time": "2026-06-16T09:17:35+00:00" + "time": "2026-10-03T15:54:38+00:00" }, { "name": "phpunit/php-code-coverage", @@ -6064,16 +6072,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.5.56", + "version": "11.5.57", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "5f83edffa6967c3db468d48a695ec7bcb02e9256" + "reference": "36b75bf56a8535623f5b3e24b27ea1823759da1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5f83edffa6967c3db468d48a695ec7bcb02e9256", - "reference": "5f83edffa6967c3db468d48a695ec7bcb02e9256", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/36b75bf56a8535623f5b3e24b27ea1823759da1a", + "reference": "36b75bf56a8535623f5b3e24b27ea1823759da1a", "shasum": "" }, "require": { @@ -6083,7 +6091,7 @@ "ext-libxml": "*", "ext-mbstring": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.4", + "myclabs/deep-copy": "^1.14.0", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", @@ -6146,7 +6154,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.56" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.57" }, "funding": [ { @@ -6154,7 +6162,7 @@ "type": "other" } ], - "time": "2026-07-06T14:52:39+00:00" + "time": "2026-10-05T05:47:54+00:00" }, { "name": "roave/security-advisories", @@ -6162,12 +6170,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "eddf5ff07ff44f9c121b404971f5577e81602779" + "reference": "7ffb508d0fec1adae95e086e0c7e2cdf1ee5f02f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/eddf5ff07ff44f9c121b404971f5577e81602779", - "reference": "eddf5ff07ff44f9c121b404971f5577e81602779", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/7ffb508d0fec1adae95e086e0c7e2cdf1ee5f02f", + "reference": "7ffb508d0fec1adae95e086e0c7e2cdf1ee5f02f", "shasum": "" }, "conflict": { @@ -6206,7 +6214,7 @@ "andreapollastri/cipi": "<=3.1.15", "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<1.0.2|>=2,<2.2.5", "aoe/restler": "<1.7.1", - "apache-solr-for-typo3/solr": "<11.6.6|>=12,<12.1.4|>=13,<13.1.4", + "apache-solr-for-typo3/solr": "<11.2.8|>=11.5,<11.6.6|>=12,<12.1.4|>=13,<13.1.4", "apache/thrift": "<0.24", "apereo/phpcas": "<1.6", "api-platform/core": "<4.1.30|>=4.2,<4.2.26|>=4.3,<4.3.12", @@ -6275,13 +6283,12 @@ "cadmium-org/cadmium-cms": "<=0.4.9", "cakephp/authentication": "<2.11.1|>=3,<3.3.6|>=4,<4.1.1", "cakephp/cakephp": "<4.5.12|>=4.6,<4.6.5|>=5,<5.1.10|>=5.2,<5.2.15|>=5.3,<5.3.7", - "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|>=5.1,<5.1.10|>=5.2,<5.2.15|>=5.3,<5.3.7", + "cakephp/database": ">=3,<4.5.12|>=4.6,<4.6.5|>=5,<5.1.10|>=5.2,<5.2.15|>=5.3,<5.3.7", "cakephp/debug_kit": "<4.10.3|>=5,<5.2.4", "cakephp/queue": ">=0.1.10,<2.3.1", "cardgate/magento2": "<2.0.33", "cardgate/woocommerce": "<=3.1.15", "cart2quote/module-quotation": ">=4.1.6,<4.4.6|>=5,<5.4.4", - "cart2quote/module-quotation-encoded": ">=4.1.6,<=4.4.5|>=5,<5.4.4", "cartalyst/sentry": "<2.1.7", "catfan/medoo": "<1.7.5", "causal/oidc": "<4", @@ -6289,6 +6296,7 @@ "centreon/centreon": "<22.10.15", "cesargb/laravel-magiclink": ">=2,<2.25.1", "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "chamilo/chamilo-lms": "<=2", "chriskacerguis/codeigniter-restserver": "<=2.7.1", "chrome-php/chrome": "<1.14", "ci4-cms-erp/ci4ms": "<=0.31.8", @@ -6297,7 +6305,7 @@ "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", "co-stack/fal_sftp": "<0.2.6", "cockpit-hq/cockpit": "<=2.14", - "code16/sharp": "<9.22.3", + "code16/sharp": "<9.22.5", "codeception/codeception": "<3.1.3|>=4,<4.1.22", "codeigniter/framework": "<3.1.10", "codeigniter4/framework": "<4.7.4", @@ -6455,7 +6463,7 @@ "feehi/feehicms": "<=2.1.1", "fenom/fenom": "<=2.12.1", "filament/actions": ">=3.2,<3.2.123|>=4,<=4.11.3|>=5,<=5.6.3", - "filament/filament": ">=3,<=3.3.51|>=4,<4.12.6|>=5,<5.7.6", + "filament/filament": ">=3,<=3.3.51|>=4,<4.13.2|>=5,<5.8.2", "filament/forms": ">=3,<=3.3.52", "filament/infolists": ">=3,<3.2.115|>=4,<=4.11.4|>=5,<=5.6.4", "filament/tables": ">=3,<=3.3.50|>=4,<=4.11.4|>=5,<=5.6.4", @@ -6477,6 +6485,7 @@ "floriangaerber/magnesium": "<0.3.1", "fluidtypo3/vhs": "<5.1.1", "fof/byobu": ">=0.3.0.0-beta2,<1.1.7", + "fof/oauth": "<1.7.4|>=2.0.0.0-beta1,<2.0.0.0-beta4", "fof/pretty-mail": "<=1.1.2", "fof/upload": "<1.2.3", "foodcoopshop/foodcoopshop": ">=3.2,<3.6.1", @@ -6580,6 +6589,7 @@ "james-heinrich/getid3": "<1.9.21", "james-heinrich/phpthumb": "<=1.7.23", "jasig/phpcas": "<1.3.3", + "jayanta/laravel-threat-detection": "<1.9", "jbartels/wec-map": "<3.0.3", "jcbrand/converse.js": "<3.3.3", "jleehr/canto-saas-api": "<=2", @@ -6630,7 +6640,7 @@ "lara-zeus/artemis": ">=1,<=1.0.6", "lara-zeus/dynamic-dashboard": ">=3,<=3.0.1", "laravel/fortify": "<1.11.1", - "laravel/framework": "<12.61.1|>=13,<13.12", + "laravel/framework": "<12.69|>=13,<13.30", "laravel/laravel": ">=5.4,<5.4.22", "laravel/passport": ">=13,<13.7.1", "laravel/pulse": "<1.3.1", @@ -6640,8 +6650,8 @@ "lavalite/cms": "<=10.1", "lavitto/typo3-form-to-database": "<2.2.5|>=3,<3.2.2|>=4,<4.2.3|>=5,<5.0.2", "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", - "league/commonmark": "<2.10", - "league/flysystem": "<1.1.4|>=2,<2.1.1", + "league/commonmark": "<=2.10.1", + "league/flysystem": "<=3.35.2", "league/oauth2-server": ">=8.3.2,<8.4.2|>=8.5,<8.5.3", "leantime/leantime": "<3.3", "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", @@ -6694,7 +6704,7 @@ "mediawiki/data-transfer": ">=1.39,<1.39.11|>=1.41,<1.41.3|>=1.42,<1.42.2", "mediawiki/maps": "<12.1.3", "mediawiki/matomo": "<2.4.3", - "mediawiki/semantic-media-wiki": "<4.0.2", + "mediawiki/semantic-media-wiki": "<=7.2.1", "mehrwert/phpmyadmin": "<3.2", "melisplatform/melis-asset-manager": "<5.0.1", "melisplatform/melis-cms": "<5.3.4", @@ -6717,7 +6727,7 @@ "mobiledetect/mobiledetectlib": "<2.8.32", "modx/revolution": "<=3.1", "mojo42/jirafeau": "<4.4", - "mongodb/mongodb": "<1.21.4|>=2,<2.4.1", + "mongodb/mongodb": "<1.21.5|>=2,<2.4.2", "mongodb/mongodb-extension": "<1.21.2", "monolog/monolog": ">=1.8,<1.12", "moodle/moodle": "<4.5.9|>=5.0.0.0-beta,<5.0.5|>=5.1.0.0-beta,<5.1.2", @@ -6798,7 +6808,7 @@ "paragonie/random_compat": "<2", "paragonie/sodium_compat": "<1.24.1|>=2,<2.5.1", "passbolt/passbolt_api": "<4.6.2", - "paymenter/paymenter": "<=1.5.4", + "paymenter/paymenter": "<=1.5.6", "paypal/adaptivepayments-sdk-php": "<=3.9.2", "paypal/invoice-sdk-php": "<=3.9", "paypal/merchant-sdk-php": "<3.12", @@ -6826,13 +6836,13 @@ "phpmailer/phpmailer": "<6.5", "phpmussel/phpmussel": ">=1,<1.6", "phpmyadmin/phpmyadmin": "<5.2.2", - "phpmyfaq/phpmyfaq": "<=4.1.4", + "phpmyfaq/phpmyfaq": "<4.2.0.0-alpha", "phpoffice/common": "<0.2.9", "phpoffice/math": "<=0.2", "phpoffice/phpexcel": "<=1.8.2", "phpoffice/phpspreadsheet": "<=1.30.5|>=2,<=2.1.17|>=2.2,<=2.4.6|>=3,<=3.10.6|>=4,<=5.8", "phppgadmin/phppgadmin": "<=7.13", - "phpseclib/phpseclib": "<=2.0.54|>=3,<=3.0.53", + "phpseclib/phpseclib": "<3.0.57|>=4,<4.0.1", "phpservermon/phpservermon": "<3.6", "phpsysinfo/phpsysinfo": "<=3.4.5", "phpunit/phpunit": "<8.5.52|>=9,<9.6.33|>=10,<10.5.62|>=11,<11.5.50|>=12,<12.5.8|>=12.5.21,<12.5.22|>=13.1.5,<13.1.6", @@ -6899,7 +6909,7 @@ "rap2hpoutre/laravel-log-viewer": "<0.13", "react/http": ">=0.6,<1.11.1", "really-simple-plugins/complianz-gdpr": "<6.4.2", - "redaxo/source": "<5.21.1", + "redaxo/source": "<=5.21.1", "remdex/livehelperchat": "<4.29", "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", "reportico-web/reportico": "<=8.1", @@ -6975,7 +6985,7 @@ "slim/slim": "<2.6|>=4.4,<=4.15.1", "slub/slub-events": "<3.0.3", "smarty/smarty": "<4.5.7|>=5,<5.8.4", - "snipe/snipe-it": "<8.6.3", + "snipe/snipe-it": "<8.7", "socalnick/scn-social-auth": "<1.15.2", "socialiteproviders/steam": "<1.1", "solidinvoice/solidinvoice": "<=2.3.15", @@ -7004,7 +7014,7 @@ "subhh/libconnect": "<7.0.8|>=8,<8.1", "sukohi/surpass": "<1", "sulu/form-bundle": ">=2,<2.5.3", - "sulu/sulu": "<=2.6.24|>=3,<3.0.8", + "sulu/sulu": "<2.6.25|>=3,<3.0.8", "sumocoders/framework-user-bundle": "<1.4", "superbig/craft-audit": "<3.0.2", "svewap/a21glossary": "<=0.4.10", @@ -7142,6 +7152,7 @@ "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", "ua-parser/uap-php": "<3.8", "uasoft-indonesia/badaso": "<=2.9.7", + "ueberdosis/tiptap-php": "<2.1.1", "unisharp/laravel-filemanager": "<2.9.1", "universal-omega/dynamic-page-list3": "<3.6.4", "unopim/unopim": "<=0.3", @@ -7151,7 +7162,7 @@ "uvdesk/core-framework": "<=1.1.1", "vanilla/safecurl": "<0.9.2", "verbb/comments": "<1.5.5", - "verbb/formie": "<3.1.28", + "verbb/formie": "<3.1.31", "verbb/image-resizer": "<2.0.9", "verbb/knock-knock": "<1.2.8", "verot/class.upload.php": "<=2.1.6", @@ -7194,7 +7205,7 @@ "woocommerce/woocommerce": "<6.6|>=8.8,<8.8.5|>=8.9,<8.9.3", "wp-cli/wp-cli": ">=0.12,<2.5", "wp-coding-standards/wpcs": ">=0.14.1,<3.4.1", - "wp-graphql/wp-graphql": "<=2.6", + "wp-graphql/wp-graphql": "<2.22.2", "wp-premium/gravityforms": "<2.4.21", "wpanel/wpanel4-cms": "<=4.3.1", "wpcloud/wp-stateless": "<3.2", @@ -7225,6 +7236,7 @@ "yuan1994/tpadmin": "<=1.3.12", "yungifez/skuul": "<=2.6.5", "z-push/z-push-dev": "<2.7.6", + "zbateson/mail-mime-parser": "<3.0.6|>=4,<4.0.2", "zencart/zencart": "<=1.5.7.0-beta", "zendesk/zendesk_api_client_php": "<2.2.11", "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", @@ -7299,7 +7311,7 @@ "type": "tidelift" } ], - "time": "2026-09-14T17:48:00+00:00" + "time": "2026-10-07T17:18:05+00:00" }, { "name": "sanmai/di-container", @@ -7509,16 +7521,16 @@ }, { "name": "sanmai/pipeline", - "version": "7.10", + "version": "7.12", "source": { "type": "git", "url": "https://github.com/sanmai/pipeline.git", - "reference": "a8e4e57a6031efc7a92defd13fed9c1c4c73fc71" + "reference": "e7c1f115790ae68ea22f30a646578c587a691399" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sanmai/pipeline/zipball/a8e4e57a6031efc7a92defd13fed9c1c4c73fc71", - "reference": "a8e4e57a6031efc7a92defd13fed9c1c4c73fc71", + "url": "https://api.github.com/repos/sanmai/pipeline/zipball/e7c1f115790ae68ea22f30a646578c587a691399", + "reference": "e7c1f115790ae68ea22f30a646578c587a691399", "shasum": "" }, "require": { @@ -7535,7 +7547,6 @@ "phpstan/phpstan": "^2", "phpunit/phpunit": "^11 || ^12", "sanmai/phpstan-rules": "^0.3.11", - "sanmai/phpunit-double-colon-syntax": "^0.1.1", "vimeo/psalm": ">=2" }, "type": "library", @@ -7565,7 +7576,7 @@ "description": "General-purpose collections pipeline", "support": { "issues": "https://github.com/sanmai/pipeline/issues", - "source": "https://github.com/sanmai/pipeline/tree/7.10" + "source": "https://github.com/sanmai/pipeline/tree/7.12" }, "funding": [ { @@ -7573,7 +7584,7 @@ "type": "github" } ], - "time": "2026-08-03T04:56:22+00:00" + "time": "2026-09-30T13:46:33+00:00" }, { "name": "sebastian/cli-parser", @@ -8759,16 +8770,16 @@ }, { "name": "symfony/framework-bundle", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "b5d67475e1c444bb71f879f79d01ff10ae980662" + "reference": "78c28ec21e3ef4bd8a72de949d0ea2dead1e3f95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/b5d67475e1c444bb71f879f79d01ff10ae980662", - "reference": "b5d67475e1c444bb71f879f79d01ff10ae980662", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/78c28ec21e3ef4bd8a72de949d0ea2dead1e3f95", + "reference": "78c28ec21e3ef4bd8a72de949d0ea2dead1e3f95", "shasum": "" }, "require": { @@ -8777,7 +8788,7 @@ "php": ">=8.4.1", "symfony/cache": "^7.4|^8.0", "symfony/config": "^7.4.4|^8.0.4", - "symfony/dependency-injection": "^8.1.2", + "symfony/dependency-injection": "^8.1.8", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^7.4|^8.0", "symfony/event-dispatcher": "^8.1", @@ -8808,7 +8819,6 @@ "symfony/workflow": "<7.4" }, "require-dev": { - "doctrine/persistence": "^1.3|^2|^3", "dragonmantank/cron-expression": "^3.1", "phpdocumentor/reflection-docblock": "^5.2|^6.0", "phpstan/phpdoc-parser": "^1.0|^2.0", @@ -8879,7 +8889,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/v8.1.7" + "source": "https://github.com/symfony/framework-bundle/tree/v8.1.8" }, "funding": [ { @@ -8899,20 +8909,20 @@ "type": "tidelift" } ], - "time": "2026-09-14T09:21:44+00:00" + "time": "2026-09-28T19:13:15+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.37.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" + "reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", - "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74", + "reference": "9c6a5d6b01ca51d486c813e9a9c0ed55f208bb74", "shasum": "" }, "require": { @@ -8963,7 +8973,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.43.0" }, "funding": [ { @@ -8983,20 +8993,20 @@ "type": "tidelift" } ], - "time": "2026-04-10T16:19:22+00:00" + "time": "2026-09-25T15:50:05+00:00" }, { "name": "symfony/polyfill-php86", - "version": "v1.41.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php86.git", - "reference": "6bc356ed3d8dbfeea8f0de235e34d670704e880e" + "reference": "8840df45b24f33a49dc419fa18dc0057231ae1d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php86/zipball/6bc356ed3d8dbfeea8f0de235e34d670704e880e", - "reference": "6bc356ed3d8dbfeea8f0de235e34d670704e880e", + "url": "https://api.github.com/repos/symfony/polyfill-php86/zipball/8840df45b24f33a49dc419fa18dc0057231ae1d8", + "reference": "8840df45b24f33a49dc419fa18dc0057231ae1d8", "shasum": "" }, "require": { @@ -9043,7 +9053,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php86/tree/v1.41.0" + "source": "https://github.com/symfony/polyfill-php86/tree/v1.43.0" }, "funding": [ { @@ -9063,20 +9073,20 @@ "type": "tidelift" } ], - "time": "2026-07-02T13:42:24+00:00" + "time": "2026-09-25T15:46:47+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.37.0", + "version": "v1.43.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94" + "reference": "b23ff8245cc5c4479ea2be3d0132d2e6dd433993" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94", - "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/b23ff8245cc5c4479ea2be3d0132d2e6dd433993", + "reference": "b23ff8245cc5c4479ea2be3d0132d2e6dd433993", "shasum": "" }, "require": { @@ -9126,7 +9136,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.43.0" }, "funding": [ { @@ -9146,7 +9156,7 @@ "type": "tidelift" } ], - "time": "2026-04-10T16:19:22+00:00" + "time": "2026-09-24T05:20:52+00:00" }, { "name": "symfony/process", @@ -9215,16 +9225,16 @@ }, { "name": "symfony/routing", - "version": "v8.1.6", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "3c188091b6b4fa2e4bc83a135caede12deb8576c" + "reference": "e46d741c56485441f37104a3e7eace4e17ed91f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/3c188091b6b4fa2e4bc83a135caede12deb8576c", - "reference": "3c188091b6b4fa2e4bc83a135caede12deb8576c", + "url": "https://api.github.com/repos/symfony/routing/zipball/e46d741c56485441f37104a3e7eace4e17ed91f9", + "reference": "e46d741c56485441f37104a3e7eace4e17ed91f9", "shasum": "" }, "require": { @@ -9271,7 +9281,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v8.1.6" + "source": "https://github.com/symfony/routing/tree/v8.1.8" }, "funding": [ { @@ -9291,7 +9301,7 @@ "type": "tidelift" } ], - "time": "2026-08-17T13:18:34+00:00" + "time": "2026-09-28T19:13:15+00:00" }, { "name": "symfony/translation-contracts", @@ -9569,16 +9579,16 @@ }, { "name": "symfony/uid", - "version": "v8.1.5", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "a08aef47989093f32fe50fd11859be1b427df389" + "reference": "f412a0b5edd75eb3104a93bd0d11fd2ea3da34e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/a08aef47989093f32fe50fd11859be1b427df389", - "reference": "a08aef47989093f32fe50fd11859be1b427df389", + "url": "https://api.github.com/repos/symfony/uid/zipball/f412a0b5edd75eb3104a93bd0d11fd2ea3da34e4", + "reference": "f412a0b5edd75eb3104a93bd0d11fd2ea3da34e4", "shasum": "" }, "require": { @@ -9623,7 +9633,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v8.1.5" + "source": "https://github.com/symfony/uid/tree/v8.1.8" }, "funding": [ { @@ -9643,20 +9653,20 @@ "type": "tidelift" } ], - "time": "2026-08-11T13:39:01+00:00" + "time": "2026-09-23T17:45:45+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v8.1.7", + "version": "v8.1.8", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "0b70c60cf63518375b59b0907712de79fa8162b7" + "reference": "bd30b3f8e2cafe758d71c2237dc09544e144402e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/0b70c60cf63518375b59b0907712de79fa8162b7", - "reference": "0b70c60cf63518375b59b0907712de79fa8162b7", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/bd30b3f8e2cafe758d71c2237dc09544e144402e", + "reference": "bd30b3f8e2cafe758d71c2237dc09544e144402e", "shasum": "" }, "require": { @@ -9708,7 +9718,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v8.1.7" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v8.1.8" }, "funding": [ { @@ -9728,7 +9738,7 @@ "type": "tidelift" } ], - "time": "2026-09-04T10:14:04+00:00" + "time": "2026-09-28T19:13:15+00:00" }, { "name": "thecodingmachine/safe", @@ -9925,16 +9935,16 @@ }, { "name": "twig/twig", - "version": "v3.28.0", + "version": "v3.30.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b" + "reference": "8c737079b726af72ff8ef3c595be9f6a810ea1ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/597c12ed286fb9d1701a36684ce6e0cbe28ebc8b", - "reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/8c737079b726af72ff8ef3c595be9f6a810ea1ef", + "reference": "8c737079b726af72ff8ef3c595be9f6a810ea1ef", "shasum": "" }, "require": { @@ -9989,7 +9999,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.28.0" + "source": "https://github.com/twigphp/Twig/tree/v3.30.0" }, "funding": [ { @@ -10001,20 +10011,20 @@ "type": "tidelift" } ], - "time": "2026-07-03T20:44:34+00:00" + "time": "2026-09-25T13:20:01+00:00" }, { "name": "webmozart/assert", - "version": "2.4.1", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70" + "reference": "8a163706bbcac613733dba03f51e13b5eb1bb819" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/2ccb7c2e821038c03a3e6e1700c570c158c55f70", - "reference": "2ccb7c2e821038c03a3e6e1700c570c158c55f70", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/8a163706bbcac613733dba03f51e13b5eb1bb819", + "reference": "8a163706bbcac613733dba03f51e13b5eb1bb819", "shasum": "" }, "require": { @@ -10065,9 +10075,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/2.4.1" + "source": "https://github.com/webmozarts/assert/tree/2.5.0" }, - "time": "2026-06-15T15:31:57+00:00" + "time": "2026-10-05T23:14:19+00:00" }, { "name": "wnx/commonmark-markdown-renderer", diff --git a/docs/configuration.md b/docs/configuration.md index 005b08e7..536ad951 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -81,6 +81,19 @@ patchlevel_event_sourcing: If you want to learn more about custom headers, read the [library documentation](/docs/event-sourcing/latest/message/#custom-headers). ::: +## Metadata Cache + +Aggregates, events and subscribers are described with attributes. +In production, meaning without `kernel.debug`, the registries and the metadata are cached +in php files in the build directory, which are created by `cache:warmup`. +This includes the hydrator metadata of your events, headers and aggregates with snapshots. +Until then, they are created on every request. +There is nothing to configure, the cache is renewed with every new build, e.g. by `cache:clear`. + +:::note +With `kernel.debug`, nothing is cached, so that changes to your classes are picked up immediately. +::: + ## Connection You have to specify the connection url to the event store. diff --git a/src/CacheWarmer/HydratorMetadataCacheWarmer.php b/src/CacheWarmer/HydratorMetadataCacheWarmer.php new file mode 100644 index 00000000..3d286c7b --- /dev/null +++ b/src/CacheWarmer/HydratorMetadataCacheWarmer.php @@ -0,0 +1,91 @@ + $aggregatePaths + * @param list $eventPaths + */ + public function __construct( + private readonly StackHydratorBuilder|HydratorMetadataFactory $hydrator, + private readonly AggregateRootRegistryFactory $aggregateRootRegistryFactory, + private readonly EventRegistryFactory $eventRegistryFactory, + private readonly AggregateRootMetadataFactory $aggregateRootMetadataFactory, + private readonly MessageHeaderRegistry $messageHeaderRegistry, + private readonly array $aggregatePaths, + private readonly array $eventPaths, + private readonly string $phpArrayFile, + ) { + } + + public function isOptional(): bool + { + return true; + } + + /** @return array classes to preload */ + public function warmUp(string $cacheDir, string|null $buildDir = null): array + { + // the file lives in the build dir, so it is already up to date if it exists + if (is_file($this->phpArrayFile)) { + return []; + } + + // without deep cloning, the array adapter keeps the objects as they are, which can then be exported + $cache = new ArrayAdapter(0, false); + + $hydratorMetadataFactory = $this->hydrator instanceof StackHydratorBuilder + ? (clone $this->hydrator)->setCache($cache)->build() + : new Psr6HydratorMetadataFactory($this->hydrator, $cache); + + // aggregates are only hydrated for snapshots, events and headers are hydrated when they are (de)serialized + $hydratedClasses = array_values($this->messageHeaderRegistry->headerClasses()); + + foreach ($this->aggregateRootRegistryFactory->create($this->aggregatePaths)->aggregateClasses() as $aggregateClass) { + if ($this->aggregateRootMetadataFactory->metadata($aggregateClass)->snapshot === null) { + continue; + } + + $hydratedClasses[] = $aggregateClass; + } + + foreach ($this->eventRegistryFactory->create($this->eventPaths)->eventClasses() as $eventClass) { + $hydratedClasses[] = $eventClass; + } + + foreach (array_unique($hydratedClasses) as $hydratedClass) { + $hydratorMetadataFactory->metadata($hydratedClass); + } + + $values = array_filter($cache->getValues(), static fn (mixed $value): bool => $value !== null); + + return (new PhpArrayAdapter($this->phpArrayFile, new NullAdapter()))->warmUp($values); + } +} diff --git a/src/CacheWarmer/MetadataCacheWarmer.php b/src/CacheWarmer/MetadataCacheWarmer.php new file mode 100644 index 00000000..bdd9973c --- /dev/null +++ b/src/CacheWarmer/MetadataCacheWarmer.php @@ -0,0 +1,92 @@ + $aggregatePaths + * @param list $eventPaths + * @param list $subscriberClasses + */ + public function __construct( + private readonly AggregateRootRegistryFactory $aggregateRootRegistryFactory, + private readonly EventRegistryFactory $eventRegistryFactory, + private readonly AggregateRootMetadataFactory $aggregateRootMetadataFactory, + private readonly EventMetadataFactory $eventMetadataFactory, + private readonly SubscriberMetadataFactory $subscriberMetadataFactory, + private readonly array $aggregatePaths, + private readonly array $eventPaths, + private readonly array $subscriberClasses, + private readonly string $phpArrayFile, + ) { + } + + public function isOptional(): bool + { + return true; + } + + /** @return array classes to preload */ + public function warmUp(string $cacheDir, string|null $buildDir = null): array + { + // the file lives in the build dir, so it is already up to date if it exists + if (is_file($this->phpArrayFile)) { + return []; + } + + // without deep cloning, the array adapter keeps the objects as they are, which can then be exported + $cache = new ArrayAdapter(0, false); + + $aggregateRootRegistry = (new Psr6AggregateRootRegistryFactory($this->aggregateRootRegistryFactory, $cache)) + ->create($this->aggregatePaths); + $eventRegistry = (new Psr6EventRegistryFactory($this->eventRegistryFactory, $cache)) + ->create($this->eventPaths); + + $aggregateRootMetadataFactory = new Psr6AggregateRootMetadataFactory($this->aggregateRootMetadataFactory, $cache); + $eventMetadataFactory = new Psr6EventMetadataFactory($this->eventMetadataFactory, $cache); + $subscriberMetadataFactory = new Psr6SubscriberMetadataFactory($this->subscriberMetadataFactory, $cache); + + foreach ($aggregateRootRegistry->aggregateClasses() as $aggregateClass) { + $aggregateRootMetadataFactory->metadata($aggregateClass); + } + + foreach ($eventRegistry->eventClasses() as $eventClass) { + $eventMetadataFactory->metadata($eventClass); + } + + foreach ($this->subscriberClasses as $subscriberClass) { + $subscriberMetadataFactory->metadata($subscriberClass); + } + + $values = array_filter($cache->getValues(), static fn (mixed $value): bool => $value !== null); + + return (new PhpArrayAdapter($this->phpArrayFile, new NullAdapter()))->warmUp($values); + } +} diff --git a/src/DependencyInjection/AggregateRootRegistryResolver.php b/src/DependencyInjection/AggregateRootRegistryResolver.php new file mode 100644 index 00000000..93a03566 --- /dev/null +++ b/src/DependencyInjection/AggregateRootRegistryResolver.php @@ -0,0 +1,31 @@ +hasDefinition(AggregateRootRegistry::class)) { + return null; + } + + /** @var list $paths */ + $paths = $container->getParameterBag()->resolveValue( + $container->getDefinition(AggregateRootRegistry::class)->getArgument(0), + ); + + return (new AttributeAggregateRootRegistryFactory())->create($paths); + } +} diff --git a/src/DependencyInjection/CommandHandlerCompilerPass.php b/src/DependencyInjection/CommandHandlerCompilerPass.php index a078c79b..43dbf4dd 100644 --- a/src/DependencyInjection/CommandHandlerCompilerPass.php +++ b/src/DependencyInjection/CommandHandlerCompilerPass.php @@ -30,8 +30,11 @@ public function process(ContainerBuilder $container): void $container->getParameter('patchlevel_event_sourcing.aggregate_handlers.bus'), ); - /** @var AggregateRootRegistry $aggregateRootRegistry */ - $aggregateRootRegistry = $container->get(AggregateRootRegistry::class); + $aggregateRootRegistry = AggregateRootRegistryResolver::resolve($container); + + if (!$aggregateRootRegistry instanceof AggregateRootRegistry) { + return; + } foreach ($aggregateRootRegistry->aggregateClasses() as $aggregateName => $aggregateClass) { $parameterResolverId = sprintf('.event_sourcing.handler_parameter_resolver.%s', $aggregateName); diff --git a/src/DependencyInjection/HandlerServiceLocatorCompilerPass.php b/src/DependencyInjection/HandlerServiceLocatorCompilerPass.php index 87eb52a6..36b00be2 100644 --- a/src/DependencyInjection/HandlerServiceLocatorCompilerPass.php +++ b/src/DependencyInjection/HandlerServiceLocatorCompilerPass.php @@ -32,8 +32,11 @@ public function process(ContainerBuilder $container): void return; } - /** @var AggregateRootRegistry $aggregateRootRegistry */ - $aggregateRootRegistry = $container->get(AggregateRootRegistry::class); + $aggregateRootRegistry = AggregateRootRegistryResolver::resolve($container); + + if (!$aggregateRootRegistry instanceof AggregateRootRegistry) { + return; + } foreach ($aggregateRootRegistry->aggregateClasses() as $aggregateName => $aggregateClass) { $parameterResolverId = sprintf('.event_sourcing.handler_parameter_resolver.%s', $aggregateName); diff --git a/src/DependencyInjection/MetadataCacheWarmerCompilerPass.php b/src/DependencyInjection/MetadataCacheWarmerCompilerPass.php new file mode 100644 index 00000000..3b6912d0 --- /dev/null +++ b/src/DependencyInjection/MetadataCacheWarmerCompilerPass.php @@ -0,0 +1,45 @@ +hasDefinition(MetadataCacheWarmer::class)) { + return; + } + + $subscriberClasses = []; + + foreach (array_keys($container->findTaggedServiceIds('event_sourcing.subscriber')) as $id) { + $class = $container->getParameterBag()->resolveValue($container->getDefinition($id)->getClass()); + + if (!is_string($class) || !class_exists($class)) { + continue; + } + + $subscriberClasses[] = $class; + } + + $container->getDefinition(MetadataCacheWarmer::class) + ->setArgument(7, array_values(array_unique($subscriberClasses))); + } +} diff --git a/src/DependencyInjection/PatchlevelEventSourcingExtension.php b/src/DependencyInjection/PatchlevelEventSourcingExtension.php index 8d9d6f7c..d236d2de 100644 --- a/src/DependencyInjection/PatchlevelEventSourcingExtension.php +++ b/src/DependencyInjection/PatchlevelEventSourcingExtension.php @@ -59,14 +59,19 @@ use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootMetadataFactory; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AttributeAggregateRootRegistryFactory; +use Patchlevel\EventSourcing\Metadata\AggregateRoot\Psr6AggregateRootMetadataFactory; +use Patchlevel\EventSourcing\Metadata\AggregateRoot\Psr6AggregateRootRegistryFactory; use Patchlevel\EventSourcing\Metadata\Event\AttributeEventMetadataFactory; use Patchlevel\EventSourcing\Metadata\Event\AttributeEventRegistryFactory; use Patchlevel\EventSourcing\Metadata\Event\EventMetadataFactory; use Patchlevel\EventSourcing\Metadata\Event\EventRegistry; +use Patchlevel\EventSourcing\Metadata\Event\Psr6EventMetadataFactory; +use Patchlevel\EventSourcing\Metadata\Event\Psr6EventRegistryFactory; use Patchlevel\EventSourcing\Metadata\Message\AttributeMessageHeaderRegistryFactory; use Patchlevel\EventSourcing\Metadata\Message\MessageHeaderRegistry; use Patchlevel\EventSourcing\Metadata\Message\MessageHeaderRegistryFactory; use Patchlevel\EventSourcing\Metadata\Subscriber\AttributeSubscriberMetadataFactory; +use Patchlevel\EventSourcing\Metadata\Subscriber\Psr6SubscriberMetadataFactory; use Patchlevel\EventSourcing\Metadata\Subscriber\SubscriberMetadataFactory; use Patchlevel\EventSourcing\QueryBus\QueryBus; use Patchlevel\EventSourcing\Repository\DefaultRepositoryManager; @@ -121,6 +126,8 @@ use Patchlevel\EventSourcing\Subscription\Subscriber\SubscriberAccessorRepository; use Patchlevel\EventSourcing\Subscription\Subscriber\SubscriberHelper; use Patchlevel\EventSourcingBundle\Attribute\AsListener; +use Patchlevel\EventSourcingBundle\CacheWarmer\HydratorMetadataCacheWarmer; +use Patchlevel\EventSourcingBundle\CacheWarmer\MetadataCacheWarmer; use Patchlevel\EventSourcingBundle\Clock\FrozenClockFactory; use Patchlevel\EventSourcingBundle\CommandBus\SymfonyCommandBus; use Patchlevel\EventSourcingBundle\DataCollector\EventSourcingCollector; @@ -155,14 +162,18 @@ use Patchlevel\Hydrator\Hydrator; use Patchlevel\Hydrator\Metadata\AttributeMetadataFactory; use Patchlevel\Hydrator\Metadata\MetadataFactory; +use Patchlevel\Hydrator\Metadata\Psr6MetadataFactory as Psr6HydratorMetadataFactory; use Patchlevel\Hydrator\MetadataHydrator; use Patchlevel\Hydrator\StackHydrator; use Patchlevel\Hydrator\StackHydratorBuilder; use Patchlevel\Worker\Event\WorkerRunningEvent; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Reference; @@ -208,6 +219,7 @@ public function load(array $configs, ContainerBuilder $container): void $this->configureMigration($config, $container); $this->configureValueResolver($container); $this->configureStoreMigration($config, $container); + $this->configureMetadataCache($config, $container); } /** @param Config $config */ @@ -1003,6 +1015,97 @@ private function configureAggregates(array $config, ContainerBuilder $container) $container->setAlias(RepositoryManager::class, DefaultRepositoryManager::class); } + /** + * Like in the doctrine bundle, the metadata is only cached without debug, in php files in the build dir. + * The event sourcing metadata and the hydrator metadata of events, headers and snapshot aggregates + * each have their own file, which is created by its own cache warmer. + * Until then, the metadata is created on every request. + * With debug, nothing is cached, so that changes are picked up immediately. + * + * @param Config $config + */ + private function configureMetadataCache(array $config, ContainerBuilder $container): void + { + if (!$container->hasParameter('kernel.debug') || $container->getParameter('kernel.debug')) { + return; + } + + $phpArrayFile = '%kernel.build_dir%/event_sourcing/metadata.php'; + + $container->register('event_sourcing.metadata_cache', PhpArrayAdapter::class) + ->setArguments([$phpArrayFile, new Definition(ArrayAdapter::class)]); + + $pool = new Reference('event_sourcing.metadata_cache'); + + $container->register(Psr6AggregateRootRegistryFactory::class) + ->setArguments([new Reference(AttributeAggregateRootRegistryFactory::class), $pool]); + + $container->getDefinition(AggregateRootRegistry::class) + ->setFactory([new Reference(Psr6AggregateRootRegistryFactory::class), 'create']); + + $container->register(Psr6EventRegistryFactory::class) + ->setArguments([new Reference(AttributeEventRegistryFactory::class), $pool]); + + $container->getDefinition(EventRegistry::class) + ->setFactory([new Reference(Psr6EventRegistryFactory::class), 'create']); + + $container->register(Psr6AggregateRootMetadataFactory::class) + ->setArguments([new Reference(AggregateRootMetadataAwareMetadataFactory::class), $pool]); + $container->setAlias(AggregateRootMetadataFactory::class, Psr6AggregateRootMetadataFactory::class); + + $container->register(Psr6EventMetadataFactory::class) + ->setArguments([new Reference(AttributeEventMetadataFactory::class), $pool]); + $container->setAlias(EventMetadataFactory::class, Psr6EventMetadataFactory::class); + + $container->register(Psr6SubscriberMetadataFactory::class) + ->setArguments([new Reference(AttributeSubscriberMetadataFactory::class), $pool]); + $container->setAlias(SubscriberMetadataFactory::class, Psr6SubscriberMetadataFactory::class); + + $container->register(MetadataCacheWarmer::class) + ->setArguments([ + new Reference(AttributeAggregateRootRegistryFactory::class), + new Reference(AttributeEventRegistryFactory::class), + new Reference(AggregateRootMetadataAwareMetadataFactory::class), + new Reference(AttributeEventMetadataFactory::class), + new Reference(AttributeSubscriberMetadataFactory::class), + $config['aggregates'], + $config['events'], + [], // the subscriber classes are set by the MetadataCacheWarmerCompilerPass + $phpArrayFile, + ]) + ->addTag('kernel.cache_warmer'); + + $hydratorPhpArrayFile = '%kernel.build_dir%/event_sourcing/hydrator_metadata.php'; + + $container->register('event_sourcing.hydrator_metadata_cache', PhpArrayAdapter::class) + ->setArguments([$hydratorPhpArrayFile, new Definition(ArrayAdapter::class)]); + + $hydratorPool = new Reference('event_sourcing.hydrator_metadata_cache'); + + if ($config['hydrator']['enabled']) { + $container->getDefinition(StackHydratorBuilder::class)->addMethodCall('setCache', [$hydratorPool]); + $hydrator = new Reference(StackHydratorBuilder::class); + } else { + $container->register(Psr6HydratorMetadataFactory::class) + ->setArguments([new Reference(AttributeMetadataFactory::class), $hydratorPool]); + $container->setAlias(MetadataFactory::class, Psr6HydratorMetadataFactory::class); + $hydrator = new Reference(AttributeMetadataFactory::class); + } + + $container->register(HydratorMetadataCacheWarmer::class) + ->setArguments([ + $hydrator, + new Reference(AttributeAggregateRootRegistryFactory::class), + new Reference(AttributeEventRegistryFactory::class), + new Reference(AggregateRootMetadataAwareMetadataFactory::class), + new Reference(MessageHeaderRegistry::class), + $config['aggregates'], + $config['events'], + $hydratorPhpArrayFile, + ]) + ->addTag('kernel.cache_warmer'); + } + private function configureCommands(ContainerBuilder $container): void { $container->register(ShowCommand::class) diff --git a/src/DependencyInjection/RepositoryCompilerPass.php b/src/DependencyInjection/RepositoryCompilerPass.php index 83960f4d..338daa65 100644 --- a/src/DependencyInjection/RepositoryCompilerPass.php +++ b/src/DependencyInjection/RepositoryCompilerPass.php @@ -9,7 +9,6 @@ use Patchlevel\EventSourcing\Repository\RepositoryManager; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; @@ -18,7 +17,7 @@ final class RepositoryCompilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container): void { - $aggregateRootRegistry = $container->get(AggregateRootRegistry::class, ContainerInterface::NULL_ON_INVALID_REFERENCE); + $aggregateRootRegistry = AggregateRootRegistryResolver::resolve($container); if (!$aggregateRootRegistry instanceof AggregateRootRegistry) { return; diff --git a/src/PatchlevelEventSourcingBundle.php b/src/PatchlevelEventSourcingBundle.php index 78a641e5..812bc0dd 100644 --- a/src/PatchlevelEventSourcingBundle.php +++ b/src/PatchlevelEventSourcingBundle.php @@ -8,6 +8,7 @@ use Patchlevel\EventSourcingBundle\DependencyInjection\DoctrineCleanupCompilerPass; use Patchlevel\EventSourcingBundle\DependencyInjection\HandlerServiceLocatorCompilerPass; use Patchlevel\EventSourcingBundle\DependencyInjection\HydratorCompilerPass; +use Patchlevel\EventSourcingBundle\DependencyInjection\MetadataCacheWarmerCompilerPass; use Patchlevel\EventSourcingBundle\DependencyInjection\QueryHandlerCompilerPass; use Patchlevel\EventSourcingBundle\DependencyInjection\RepositoryCompilerPass; use Patchlevel\EventSourcingBundle\DependencyInjection\SubscriberGuardCompilePass; @@ -27,5 +28,6 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new TranslatorCompilerPass()); $container->addCompilerPass(new DoctrineCleanupCompilerPass()); $container->addCompilerPass(new HydratorCompilerPass()); + $container->addCompilerPass(new MetadataCacheWarmerCompilerPass()); } } diff --git a/tests/Unit/PatchlevelEventSourcingBundleTest.php b/tests/Unit/PatchlevelEventSourcingBundleTest.php index 1046a80d..5f558c9f 100644 --- a/tests/Unit/PatchlevelEventSourcingBundleTest.php +++ b/tests/Unit/PatchlevelEventSourcingBundleTest.php @@ -14,6 +14,7 @@ use Doctrine\Migrations\Tools\Console\Command\StatusCommand; use Doctrine\Persistence\ManagerRegistry; use InvalidArgumentException; +use Patchlevel\EventSourcing\Aggregate\CustomId; use Patchlevel\EventSourcing\Attribute\Aggregate; use Patchlevel\EventSourcing\Attribute\Event; use Patchlevel\EventSourcing\Clock\FrozenClock; @@ -46,9 +47,19 @@ use Patchlevel\EventSourcing\Message\Translator\AggregateToStreamHeaderTranslator; use Patchlevel\EventSourcing\Message\Translator\ExcludeEventWithHeaderTranslator; use Patchlevel\EventSourcing\Message\Translator\RecalculatePlayheadTranslator; +use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootMetadata; +use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootMetadataFactory; use Patchlevel\EventSourcing\Metadata\AggregateRoot\AggregateRootRegistry; +use Patchlevel\EventSourcing\Metadata\AggregateRoot\Psr6AggregateRootMetadataFactory; +use Patchlevel\EventSourcing\Metadata\Event\AttributeEventMetadataFactory; +use Patchlevel\EventSourcing\Metadata\Event\EventMetadata; +use Patchlevel\EventSourcing\Metadata\Event\EventMetadataFactory; use Patchlevel\EventSourcing\Metadata\Event\EventRegistry; +use Patchlevel\EventSourcing\Metadata\Event\Psr6EventMetadataFactory; use Patchlevel\EventSourcing\Metadata\Message\MessageHeaderRegistry; +use Patchlevel\EventSourcing\Metadata\Subscriber\Psr6SubscriberMetadataFactory; +use Patchlevel\EventSourcing\Metadata\Subscriber\SubscriberMetadata; +use Patchlevel\EventSourcing\Metadata\Subscriber\SubscriberMetadataFactory; use Patchlevel\EventSourcing\QueryBus\QueryBus; use Patchlevel\EventSourcing\Repository\DefaultRepository; use Patchlevel\EventSourcing\Repository\DefaultRepositoryManager; @@ -90,6 +101,8 @@ use Patchlevel\EventSourcing\Subscription\Store\InMemorySubscriptionStore; use Patchlevel\EventSourcing\Subscription\Store\SubscriptionStore; use Patchlevel\EventSourcing\Subscription\Subscriber\MetadataSubscriberAccessorRepository; +use Patchlevel\EventSourcingBundle\CacheWarmer\HydratorMetadataCacheWarmer; +use Patchlevel\EventSourcingBundle\CacheWarmer\MetadataCacheWarmer; use Patchlevel\EventSourcingBundle\DependencyInjection\PatchlevelEventSourcingExtension; use Patchlevel\EventSourcingBundle\EventBus\SymfonyEventBus; use Patchlevel\EventSourcingBundle\Normalizer\SymfonyExtension; @@ -118,6 +131,9 @@ use Patchlevel\Hydrator\Extension\Lifecycle\LifecycleExtension; use Patchlevel\Hydrator\Guesser\BuiltInGuesser; use Patchlevel\Hydrator\Hydrator; +use Patchlevel\Hydrator\Metadata\ClassMetadata; +use Patchlevel\Hydrator\Metadata\MetadataFactory as HydratorMetadataFactory; +use Patchlevel\Hydrator\Metadata\Psr6MetadataFactory as Psr6HydratorMetadataFactory; use Patchlevel\Hydrator\MetadataHydrator; use Patchlevel\Hydrator\StackHydrator; use PHPUnit\Framework\Attributes\RequiresMethod; @@ -127,6 +143,8 @@ use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\Adapter\NullAdapter; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; @@ -137,7 +155,10 @@ use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter; use Symfony\Component\Messenger\MessageBusInterface; +use function hash; use function sprintf; +use function sys_get_temp_dir; +use function uniqid; final class PatchlevelEventSourcingBundleTest extends TestCase { @@ -956,6 +977,239 @@ public function testMessageHeaderRegistry(): void self::assertTrue($messageHeaderRegistry->hasHeaderClass(CustomHeader::class)); } + public function testMetadataIsNotCachedWithDebug(): void + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', true); + + $this->compileContainer( + $container, + [ + 'patchlevel_event_sourcing' => [ + 'connection' => ['service' => 'doctrine.dbal.eventstore_connection'], + ], + ], + ); + + self::assertFalse($container->hasDefinition(MetadataCacheWarmer::class)); + self::assertFalse($container->hasDefinition(HydratorMetadataCacheWarmer::class)); + self::assertInstanceOf(AttributeEventMetadataFactory::class, $container->get(EventMetadataFactory::class)); + } + + public function testMetadataCache(): void + { + $buildDir = sys_get_temp_dir() . '/' . uniqid('event_sourcing_build_', true); + + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + $container->setParameter('kernel.build_dir', $buildDir); + $container->setDefinition(ProfileSubscriber::class, new Definition(ProfileSubscriber::class)) + ->setAutoconfigured(true); + + $this->compileContainer( + $container, + [ + 'patchlevel_event_sourcing' => [ + 'connection' => ['service' => 'doctrine.dbal.eventstore_connection'], + 'aggregates' => [__DIR__ . '/../Fixtures'], + 'events' => [__DIR__ . '/../Fixtures'], + ], + ], + ); + + self::assertInstanceOf( + Psr6AggregateRootMetadataFactory::class, + $container->get(AggregateRootMetadataFactory::class), + ); + self::assertInstanceOf(Psr6EventMetadataFactory::class, $container->get(EventMetadataFactory::class)); + self::assertInstanceOf(Psr6SubscriberMetadataFactory::class, $container->get(SubscriberMetadataFactory::class)); + self::assertTrue($container->getDefinition(MetadataCacheWarmer::class)->hasTag('kernel.cache_warmer')); + self::assertTrue($container->getDefinition(HydratorMetadataCacheWarmer::class)->hasTag('kernel.cache_warmer')); + + $warmer = $container->get(MetadataCacheWarmer::class); + + self::assertInstanceOf(MetadataCacheWarmer::class, $warmer); + self::assertTrue($warmer->isOptional()); + + $warmer->warmUp($buildDir, $buildDir); + + $cache = new PhpArrayAdapter($buildDir . '/event_sourcing/metadata.php', new NullAdapter()); + + self::assertInstanceOf(AggregateRootRegistry::class, $cache->getItem('aggregate_root_registry')->get()); + self::assertInstanceOf(EventRegistry::class, $cache->getItem('event_registry')->get()); + self::assertInstanceOf( + AggregateRootMetadata::class, + $cache->getItem('aggregate_root_metadata_' . hash('xxh128', Profile::class))->get(), + ); + self::assertInstanceOf( + EventMetadata::class, + $cache->getItem('event_metadata_' . hash('xxh128', ProfileCreated::class))->get(), + ); + self::assertInstanceOf( + SubscriberMetadata::class, + $cache->getItem('subscriber_metadata_' . hash('xxh128', ProfileSubscriber::class))->get(), + ); + } + + public function testMetadataCacheIsUsed(): void + { + $buildDir = sys_get_temp_dir() . '/' . uniqid('event_sourcing_build_', true); + + (new PhpArrayAdapter($buildDir . '/event_sourcing/metadata.php', new NullAdapter()))->warmUp([ + 'event_registry' => new EventRegistry(['cached_event' => ProfileCreated::class]), + ]); + + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + $container->setParameter('kernel.build_dir', $buildDir); + + $this->compileContainer( + $container, + [ + 'patchlevel_event_sourcing' => [ + 'connection' => ['service' => 'doctrine.dbal.eventstore_connection'], + 'events' => [__DIR__ . '/../Fixtures'], + ], + ], + ); + + $eventRegistry = $container->get(EventRegistry::class); + + self::assertInstanceOf(EventRegistry::class, $eventRegistry); + self::assertSame(['cached_event' => ProfileCreated::class], $eventRegistry->eventClasses()); + } + + public function testHydratorMetadataCache(): void + { + $buildDir = sys_get_temp_dir() . '/' . uniqid('event_sourcing_build_', true); + $config = [ + 'patchlevel_event_sourcing' => [ + 'connection' => ['service' => 'doctrine.dbal.eventstore_connection'], + 'aggregates' => [__DIR__ . '/../Fixtures'], + 'events' => [__DIR__ . '/../Fixtures'], + 'headers' => [__DIR__ . '/../Fixtures'], + 'hydrator' => ['enabled' => true], + ], + ]; + + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + $container->setParameter('kernel.build_dir', $buildDir); + + $this->compileContainer($container, $config); + + $warmer = $container->get(HydratorMetadataCacheWarmer::class); + + self::assertInstanceOf(HydratorMetadataCacheWarmer::class, $warmer); + + $warmer->warmUp($buildDir, $buildDir); + + $cache = new PhpArrayAdapter($buildDir . '/event_sourcing/hydrator_metadata.php', new NullAdapter()); + + self::assertInstanceOf( + ClassMetadata::class, + $cache->getItem('hydrator_metadata_' . hash('xxh128', ProfileCreated::class))->get(), + ); + self::assertInstanceOf( + ClassMetadata::class, + $cache->getItem('hydrator_metadata_' . hash('xxh128', CustomHeader::class))->get(), + ); + self::assertInstanceOf( + ClassMetadata::class, + $cache->getItem('hydrator_metadata_' . hash('xxh128', SnapshotableProfile::class))->get(), + ); + self::assertFalse($cache->hasItem('hydrator_metadata_' . hash('xxh128', Profile::class))); + + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + $container->setParameter('kernel.build_dir', $buildDir); + + $this->compileContainer($container, $config); + + $hydrator = $container->get(Hydrator::class); + + self::assertInstanceOf(StackHydrator::class, $hydrator); + self::assertEquals( + new ProfileCreated(CustomId::fromString('1')), + $hydrator->hydrate(ProfileCreated::class, ['id' => '1']), + ); + self::assertSame(['id' => '1'], $hydrator->extract(new ProfileCreated(CustomId::fromString('1')))); + } + + public function testLegacyHydratorMetadataCache(): void + { + $buildDir = sys_get_temp_dir() . '/' . uniqid('event_sourcing_build_', true); + $config = [ + 'patchlevel_event_sourcing' => [ + 'connection' => ['service' => 'doctrine.dbal.eventstore_connection'], + 'events' => [__DIR__ . '/../Fixtures'], + ], + ]; + + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + $container->setParameter('kernel.build_dir', $buildDir); + + $this->compileContainer($container, $config); + + self::assertInstanceOf(Psr6HydratorMetadataFactory::class, $container->get(HydratorMetadataFactory::class)); + + $warmer = $container->get(HydratorMetadataCacheWarmer::class); + + self::assertInstanceOf(HydratorMetadataCacheWarmer::class, $warmer); + + $warmer->warmUp($buildDir, $buildDir); + + $cache = new PhpArrayAdapter($buildDir . '/event_sourcing/hydrator_metadata.php', new NullAdapter()); + + self::assertInstanceOf( + ClassMetadata::class, + $cache->getItem('hydrator_metadata_' . hash('xxh128', ProfileCreated::class))->get(), + ); + + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + $container->setParameter('kernel.build_dir', $buildDir); + + $this->compileContainer($container, $config); + + $hydrator = $container->get(Hydrator::class); + + self::assertInstanceOf(MetadataHydrator::class, $hydrator); + self::assertEquals( + new ProfileCreated(CustomId::fromString('1')), + $hydrator->hydrate(ProfileCreated::class, ['id' => '1']), + ); + self::assertSame(['id' => '1'], $hydrator->extract(new ProfileCreated(CustomId::fromString('1')))); + } + + public function testMetadataCacheIsNotUsedWhileCompiling(): void + { + $buildDir = sys_get_temp_dir() . '/' . uniqid('event_sourcing_build_', true); + + (new PhpArrayAdapter($buildDir . '/event_sourcing/metadata.php', new NullAdapter()))->warmUp([ + 'aggregate_root_registry' => new AggregateRootRegistry([]), + ]); + + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + $container->setParameter('kernel.build_dir', $buildDir); + + $this->compileContainer( + $container, + [ + 'patchlevel_event_sourcing' => [ + 'connection' => ['service' => 'doctrine.dbal.eventstore_connection'], + 'aggregates' => [__DIR__ . '/../Fixtures'], + 'command_bus' => ['service' => 'command.bus'], + ], + ], + ); + + self::assertTrue($container->hasDefinition('event_sourcing.profile.repository')); + self::assertTrue($container->hasDefinition('event_sourcing.handler.profile.create')); + } + public function testRepositoryManager(): void { $container = new ContainerBuilder();