diff --git a/.gitignore b/.gitignore index 53b81cd..e900736 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,7 @@ ###< phpunit/phpunit ### .env -docker compose.override.yml + +###> qossmic/deptrac-shim ### +/.deptrac.cache +###< qossmic/deptrac-shim ### diff --git a/composer.json b/composer.json index f760f5c..3e5b9e5 100644 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "symfony/http-client": "^7.0", "symfony/intl": "^7.0", "symfony/mailer": "^7.0", + "symfony/messenger": "^7.0", "symfony/mime": "^7.0", "symfony/monolog-bundle": "^3.10", "symfony/notifier": "^7.0", @@ -50,11 +51,13 @@ "symfony/maker-bundle": "^1.58", "symfony/phpunit-bridge": "^7.0", "symfony/stopwatch": "^7.0", - "symfony/web-profiler-bundle": "^7.0" + "symfony/web-profiler-bundle": "^7.0", + "qossmic/deptrac-shim": "^1.0" }, "config": { "allow-plugins": { - "symfony/*": true + "symfony/*": true, + "php-http/discovery": true }, "optimize-autoloader": true, "preferred-install": { @@ -64,7 +67,10 @@ }, "autoload": { "psr-4": { - "App\\": "src/" + "App\\": "src/", + "Application\\": "src/Application/", + "Domain\\": "src/Domain/", + "Infrastructure\\": "src/Infrastructure/" } }, "autoload-dev": { diff --git a/composer.lock b/composer.lock index a3c72ad..c63f9d2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e1d68fda857d3a6a99a9c9d4e0c1c4dd", + "content-hash": "a7ce5357a0524f6847becf0c63e1ef9e", "packages": [ { "name": "composer/package-versions-deprecated", @@ -174,16 +174,16 @@ }, { "name": "doctrine/collections", - "version": "2.2.1", + "version": "2.2.2", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "420480fc085bc65f3c956af13abe8e7546f94813" + "reference": "d8af7f248c74f195f7347424600fd9e17b57af59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/420480fc085bc65f3c956af13abe8e7546f94813", - "reference": "420480fc085bc65f3c956af13abe8e7546f94813", + "url": "https://api.github.com/repos/doctrine/collections/zipball/d8af7f248c74f195f7347424600fd9e17b57af59", + "reference": "d8af7f248c74f195f7347424600fd9e17b57af59", "shasum": "" }, "require": { @@ -240,7 +240,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.2.1" + "source": "https://github.com/doctrine/collections/tree/2.2.2" }, "funding": [ { @@ -256,20 +256,20 @@ "type": "tidelift" } ], - "time": "2024-03-05T22:28:45+00:00" + "time": "2024-04-18T06:56:21+00:00" }, { "name": "doctrine/dbal", - "version": "4.0.1", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "9e588fe1f38a443cb17de6b86b803d9e028e2156" + "reference": "61d79c6e379a39dc1fea6b4e50a23dfc3cd2076a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/9e588fe1f38a443cb17de6b86b803d9e028e2156", - "reference": "9e588fe1f38a443cb17de6b86b803d9e028e2156", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/61d79c6e379a39dc1fea6b4e50a23dfc3cd2076a", + "reference": "61d79c6e379a39dc1fea6b4e50a23dfc3cd2076a", "shasum": "" }, "require": { @@ -348,7 +348,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.0.1" + "source": "https://github.com/doctrine/dbal/tree/4.0.2" }, "funding": [ { @@ -364,7 +364,7 @@ "type": "tidelift" } ], - "time": "2024-03-03T15:59:11+00:00" + "time": "2024-04-25T08:29:52+00:00" }, { "name": "doctrine/deprecations", @@ -1057,16 +1057,16 @@ }, { "name": "doctrine/orm", - "version": "3.1.1", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "9c560713925ac5859342e6ff370c4c997acf2fd4" + "reference": "f79d166a4e844beb9389f23bdb44abdbf58cec38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/9c560713925ac5859342e6ff370c4c997acf2fd4", - "reference": "9c560713925ac5859342e6ff370c4c997acf2fd4", + "url": "https://api.github.com/repos/doctrine/orm/zipball/f79d166a4e844beb9389f23bdb44abdbf58cec38", + "reference": "f79d166a4e844beb9389f23bdb44abdbf58cec38", "shasum": "" }, "require": { @@ -1139,9 +1139,9 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/3.1.1" + "source": "https://github.com/doctrine/orm/tree/3.1.2" }, - "time": "2024-03-21T11:37:52+00:00" + "time": "2024-04-15T14:20:40+00:00" }, { "name": "doctrine/persistence", @@ -2136,16 +2136,16 @@ }, { "name": "symfony/asset", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/asset.git", - "reference": "3ae493792fc17cc31b84e231f30f2d154575f171" + "reference": "dc7600afc7e6676b3401326ae9c9abfcee4b40c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/3ae493792fc17cc31b84e231f30f2d154575f171", - "reference": "3ae493792fc17cc31b84e231f30f2d154575f171", + "url": "https://api.github.com/repos/symfony/asset/zipball/dc7600afc7e6676b3401326ae9c9abfcee4b40c5", + "reference": "dc7600afc7e6676b3401326ae9c9abfcee4b40c5", "shasum": "" }, "require": { @@ -2185,7 +2185,7 @@ "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/asset/tree/v7.0.3" + "source": "https://github.com/symfony/asset/tree/v7.0.7" }, "funding": [ { @@ -2201,20 +2201,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/cache", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "2d0d3f92c74c445410d05374908b03e0a1131e2b" + "reference": "48e3508338987d63b0114a00c208c4cbb76e5303" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/2d0d3f92c74c445410d05374908b03e0a1131e2b", - "reference": "2d0d3f92c74c445410d05374908b03e0a1131e2b", + "url": "https://api.github.com/repos/symfony/cache/zipball/48e3508338987d63b0114a00c208c4cbb76e5303", + "reference": "48e3508338987d63b0114a00c208c4cbb76e5303", "shasum": "" }, "require": { @@ -2281,7 +2281,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.0.6" + "source": "https://github.com/symfony/cache/tree/v7.0.7" }, "funding": [ { @@ -2297,7 +2297,7 @@ "type": "tidelift" } ], - "time": "2024-03-27T19:55:25+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/cache-contracts", @@ -2377,16 +2377,16 @@ }, { "name": "symfony/clock", - "version": "v7.0.5", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "8b9d08887353d627d5f6c3bf3373b398b49051c2" + "reference": "2008671acb4a30b01c453de193cf9c80549ebda6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/8b9d08887353d627d5f6c3bf3373b398b49051c2", - "reference": "8b9d08887353d627d5f6c3bf3373b398b49051c2", + "url": "https://api.github.com/repos/symfony/clock/zipball/2008671acb4a30b01c453de193cf9c80549ebda6", + "reference": "2008671acb4a30b01c453de193cf9c80549ebda6", "shasum": "" }, "require": { @@ -2431,7 +2431,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.0.5" + "source": "https://github.com/symfony/clock/tree/v7.0.7" }, "funding": [ { @@ -2447,20 +2447,20 @@ "type": "tidelift" } ], - "time": "2024-03-02T12:46:12+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/config", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "7fc7e18a73ec8125fd95928c0340470d64760deb" + "reference": "f66f908a975500aa4594258bf454dc66e3939eac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/7fc7e18a73ec8125fd95928c0340470d64760deb", - "reference": "7fc7e18a73ec8125fd95928c0340470d64760deb", + "url": "https://api.github.com/repos/symfony/config/zipball/f66f908a975500aa4594258bf454dc66e3939eac", + "reference": "f66f908a975500aa4594258bf454dc66e3939eac", "shasum": "" }, "require": { @@ -2506,7 +2506,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v7.0.6" + "source": "https://github.com/symfony/config/tree/v7.0.7" }, "funding": [ { @@ -2522,20 +2522,20 @@ "type": "tidelift" } ], - "time": "2024-03-27T19:55:25+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/console", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5" + "reference": "c981e0e9380ce9f146416bde3150c79197ce9986" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", - "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5", + "url": "https://api.github.com/repos/symfony/console/zipball/c981e0e9380ce9f146416bde3150c79197ce9986", + "reference": "c981e0e9380ce9f146416bde3150c79197ce9986", "shasum": "" }, "require": { @@ -2599,7 +2599,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.0.6" + "source": "https://github.com/symfony/console/tree/v7.0.7" }, "funding": [ { @@ -2615,20 +2615,20 @@ "type": "tidelift" } ], - "time": "2024-04-01T11:04:53+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/dependency-injection", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "ff57b5c7d518c39eeb4e69dc0d1ec70723a117b9" + "reference": "4db1314337f4dd864113f88e08c9a7f98b1c1324" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/ff57b5c7d518c39eeb4e69dc0d1ec70723a117b9", - "reference": "ff57b5c7d518c39eeb4e69dc0d1ec70723a117b9", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/4db1314337f4dd864113f88e08c9a7f98b1c1324", + "reference": "4db1314337f4dd864113f88e08c9a7f98b1c1324", "shasum": "" }, "require": { @@ -2679,7 +2679,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v7.0.6" + "source": "https://github.com/symfony/dependency-injection/tree/v7.0.7" }, "funding": [ { @@ -2695,7 +2695,7 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/deprecation-contracts", @@ -2766,16 +2766,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "929527febf8e134eaba620de1f9396da1db0df85" + "reference": "da605530d1a75162359d494efc00f767f7fcd68a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/929527febf8e134eaba620de1f9396da1db0df85", - "reference": "929527febf8e134eaba620de1f9396da1db0df85", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/da605530d1a75162359d494efc00f767f7fcd68a", + "reference": "da605530d1a75162359d494efc00f767f7fcd68a", "shasum": "" }, "require": { @@ -2852,7 +2852,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.6" + "source": "https://github.com/symfony/doctrine-bridge/tree/v7.0.7" }, "funding": [ { @@ -2868,20 +2868,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T09:29:21+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/dotenv", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067" + "reference": "0fd573c141e1990848702d56329050efd5bf25cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067", - "reference": "8017ea2f0ff4fbda6ae1bf3f5409d5ecff982067", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/0fd573c141e1990848702d56329050efd5bf25cc", + "reference": "0fd573c141e1990848702d56329050efd5bf25cc", "shasum": "" }, "require": { @@ -2926,7 +2926,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v7.0.4" + "source": "https://github.com/symfony/dotenv/tree/v7.0.7" }, "funding": [ { @@ -2942,20 +2942,20 @@ "type": "tidelift" } ], - "time": "2024-02-09T10:53:15+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/error-handler", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "46a4cc138f799886d4bd70477c55c699d3e9dfc8" + "reference": "cf97429887e40480c847bfeb6c3991e1e2c086ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/46a4cc138f799886d4bd70477c55c699d3e9dfc8", - "reference": "46a4cc138f799886d4bd70477c55c699d3e9dfc8", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/cf97429887e40480c847bfeb6c3991e1e2c086ab", + "reference": "cf97429887e40480c847bfeb6c3991e1e2c086ab", "shasum": "" }, "require": { @@ -3001,7 +3001,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.0.6" + "source": "https://github.com/symfony/error-handler/tree/v7.0.7" }, "funding": [ { @@ -3017,20 +3017,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:57:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e" + "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/834c28d533dd0636f910909d01b9ff45cc094b5e", - "reference": "834c28d533dd0636f910909d01b9ff45cc094b5e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/db2a7fab994d67d92356bb39c367db115d9d30f9", + "reference": "db2a7fab994d67d92356bb39c367db115d9d30f9", "shasum": "" }, "require": { @@ -3081,7 +3081,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.3" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.0.7" }, "funding": [ { @@ -3097,7 +3097,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -3177,16 +3177,16 @@ }, { "name": "symfony/expression-language", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "0877c599cb260c9614f9229c0a2090d6919fd621" + "reference": "b8ec919a6d3d47fc4e7845c256d164413207bf73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/0877c599cb260c9614f9229c0a2090d6919fd621", - "reference": "0877c599cb260c9614f9229c0a2090d6919fd621", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/b8ec919a6d3d47fc4e7845c256d164413207bf73", + "reference": "b8ec919a6d3d47fc4e7845c256d164413207bf73", "shasum": "" }, "require": { @@ -3220,7 +3220,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v7.0.3" + "source": "https://github.com/symfony/expression-language/tree/v7.0.7" }, "funding": [ { @@ -3236,26 +3236,27 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/filesystem", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "408105dff4c104454100730bdfd1a9cdd993f04d" + "reference": "cc168be6fbdcdf3401f50ae863ee3818ed4338f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d", - "reference": "408105dff4c104454100730bdfd1a9cdd993f04d", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/cc168be6fbdcdf3401f50ae863ee3818ed4338f5", + "reference": "cc168be6fbdcdf3401f50ae863ee3818ed4338f5", "shasum": "" }, "require": { "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-mbstring": "~1.8" + "symfony/polyfill-mbstring": "~1.8", + "symfony/process": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -3283,7 +3284,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.0.6" + "source": "https://github.com/symfony/filesystem/tree/v7.0.7" }, "funding": [ { @@ -3299,20 +3300,20 @@ "type": "tidelift" } ], - "time": "2024-03-21T19:37:36+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/finder", - "version": "v7.0.0", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56" + "reference": "4d58f0f4fe95a30d7b538d71197135483560b97c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", - "reference": "6e5688d69f7cfc4ed4a511e96007e06c2d34ce56", + "url": "https://api.github.com/repos/symfony/finder/zipball/4d58f0f4fe95a30d7b538d71197135483560b97c", + "reference": "4d58f0f4fe95a30d7b538d71197135483560b97c", "shasum": "" }, "require": { @@ -3347,7 +3348,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.0.0" + "source": "https://github.com/symfony/finder/tree/v7.0.7" }, "funding": [ { @@ -3363,7 +3364,7 @@ "type": "tidelift" } ], - "time": "2023-10-31T17:59:56+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/flex", @@ -3432,16 +3433,16 @@ }, { "name": "symfony/form", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/form.git", - "reference": "d5db6599775a563792391d0045decc240e7ebd1e" + "reference": "b4df6a399a2b03782a0163807239db342659f54f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/form/zipball/d5db6599775a563792391d0045decc240e7ebd1e", - "reference": "d5db6599775a563792391d0045decc240e7ebd1e", + "url": "https://api.github.com/repos/symfony/form/zipball/b4df6a399a2b03782a0163807239db342659f54f", + "reference": "b4df6a399a2b03782a0163807239db342659f54f", "shasum": "" }, "require": { @@ -3508,7 +3509,7 @@ "description": "Allows to easily create, process and reuse HTML forms", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/form/tree/v7.0.6" + "source": "https://github.com/symfony/form/tree/v7.0.7" }, "funding": [ { @@ -3524,20 +3525,20 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/framework-bundle", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "5ebf6771f92d135c2bdbda7133998feb74713658" + "reference": "5d9cee370509056b8b7a5009d7112d045d8f0a64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/5ebf6771f92d135c2bdbda7133998feb74713658", - "reference": "5ebf6771f92d135c2bdbda7133998feb74713658", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/5d9cee370509056b8b7a5009d7112d045d8f0a64", + "reference": "5d9cee370509056b8b7a5009d7112d045d8f0a64", "shasum": "" }, "require": { @@ -3654,7 +3655,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v7.0.6" + "source": "https://github.com/symfony/framework-bundle/tree/v7.0.7" }, "funding": [ { @@ -3670,20 +3671,20 @@ "type": "tidelift" } ], - "time": "2024-03-27T19:55:25+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/http-client", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "6e70473909f46fe5dd3b994a0f1b20ecb6b2f858" + "reference": "6ce3c4c899051b3d7326ea1a1dda3729e29ae6d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/6e70473909f46fe5dd3b994a0f1b20ecb6b2f858", - "reference": "6e70473909f46fe5dd3b994a0f1b20ecb6b2f858", + "url": "https://api.github.com/repos/symfony/http-client/zipball/6ce3c4c899051b3d7326ea1a1dda3729e29ae6d7", + "reference": "6ce3c4c899051b3d7326ea1a1dda3729e29ae6d7", "shasum": "" }, "require": { @@ -3746,7 +3747,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.0.6" + "source": "https://github.com/symfony/http-client/tree/v7.0.7" }, "funding": [ { @@ -3762,7 +3763,7 @@ "type": "tidelift" } ], - "time": "2024-04-01T20:49:44+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/http-client-contracts", @@ -3844,16 +3845,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "8789625dcf36e5fbf753014678a1e090f1bc759c" + "reference": "0194e064b8bdc29381462f790bab04e1cac8fdc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8789625dcf36e5fbf753014678a1e090f1bc759c", - "reference": "8789625dcf36e5fbf753014678a1e090f1bc759c", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/0194e064b8bdc29381462f790bab04e1cac8fdc8", + "reference": "0194e064b8bdc29381462f790bab04e1cac8fdc8", "shasum": "" }, "require": { @@ -3901,7 +3902,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.0.6" + "source": "https://github.com/symfony/http-foundation/tree/v7.0.7" }, "funding": [ { @@ -3917,20 +3918,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:46:48+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "34c872391046d59af804af62d4573b829cfe4824" + "reference": "e07bb9bd86e7cd8ba2d3d9c618eec9d1bbe06d25" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/34c872391046d59af804af62d4573b829cfe4824", - "reference": "34c872391046d59af804af62d4573b829cfe4824", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/e07bb9bd86e7cd8ba2d3d9c618eec9d1bbe06d25", + "reference": "e07bb9bd86e7cd8ba2d3d9c618eec9d1bbe06d25", "shasum": "" }, "require": { @@ -3984,6 +3985,7 @@ "symfony/translation-contracts": "^2.5|^3", "symfony/uid": "^6.4|^7.0", "symfony/validator": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0", "symfony/var-exporter": "^6.4|^7.0", "twig/twig": "^3.0.4" }, @@ -4013,7 +4015,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.0.6" + "source": "https://github.com/symfony/http-kernel/tree/v7.0.7" }, "funding": [ { @@ -4029,20 +4031,20 @@ "type": "tidelift" } ], - "time": "2024-04-03T06:12:25+00:00" + "time": "2024-04-29T12:20:25+00:00" }, { "name": "symfony/intl", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/intl.git", - "reference": "295995df4acf6790a35b9ce6ec32b313efb11ff8" + "reference": "dd12042707110995e2e7d80103f8d9928bea8621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/intl/zipball/295995df4acf6790a35b9ce6ec32b313efb11ff8", - "reference": "295995df4acf6790a35b9ce6ec32b313efb11ff8", + "url": "https://api.github.com/repos/symfony/intl/zipball/dd12042707110995e2e7d80103f8d9928bea8621", + "reference": "dd12042707110995e2e7d80103f8d9928bea8621", "shasum": "" }, "require": { @@ -4059,7 +4061,8 @@ "Symfony\\Component\\Intl\\": "" }, "exclude-from-classmap": [ - "/Tests/" + "/Tests/", + "/Resources/data/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -4095,7 +4098,7 @@ "localization" ], "support": { - "source": "https://github.com/symfony/intl/tree/v7.0.3" + "source": "https://github.com/symfony/intl/tree/v7.0.7" }, "funding": [ { @@ -4111,20 +4114,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/mailer", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0" + "reference": "4ff41a7c7998a88cfdc31b5841ef64d9246fc56a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0", - "reference": "eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0", + "url": "https://api.github.com/repos/symfony/mailer/zipball/4ff41a7c7998a88cfdc31b5841ef64d9246fc56a", + "reference": "4ff41a7c7998a88cfdc31b5841ef64d9246fc56a", "shasum": "" }, "require": { @@ -4175,7 +4178,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.0.6" + "source": "https://github.com/symfony/mailer/tree/v7.0.7" }, "funding": [ { @@ -4191,20 +4194,106 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-18T09:29:19+00:00" + }, + { + "name": "symfony/messenger", + "version": "v7.0.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/messenger.git", + "reference": "90c217478f85d5289aae597551e2a4251e4d08c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/messenger/zipball/90c217478f85d5289aae597551e2a4251e4d08c3", + "reference": "90c217478f85d5289aae597551e2a4251e4d08c3", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/clock": "^6.4|^7.0" + }, + "conflict": { + "symfony/console": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/event-dispatcher-contracts": "<2.5", + "symfony/framework-bundle": "<6.4", + "symfony/http-kernel": "<6.4", + "symfony/serializer": "<6.4" + }, + "require-dev": { + "psr/cache": "^1.0|^2.0|^3.0", + "symfony/console": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/property-access": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/routing": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/validator": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Messenger\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Samuel Roze", + "email": "samuel.roze@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Helps applications send and receive messages to/from other applications or via message queues", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/messenger/tree/v7.0.7" + }, + "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": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/mime", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "99362408c9abdf8c7cadcf0529b6fc8b16f5ace2" + "reference": "3adbf110c306546f6f00337f421d2edca0e8d3c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/99362408c9abdf8c7cadcf0529b6fc8b16f5ace2", - "reference": "99362408c9abdf8c7cadcf0529b6fc8b16f5ace2", + "url": "https://api.github.com/repos/symfony/mime/zipball/3adbf110c306546f6f00337f421d2edca0e8d3c0", + "reference": "3adbf110c306546f6f00337f421d2edca0e8d3c0", "shasum": "" }, "require": { @@ -4259,7 +4348,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.0.6" + "source": "https://github.com/symfony/mime/tree/v7.0.7" }, "funding": [ { @@ -4275,20 +4364,20 @@ "type": "tidelift" } ], - "time": "2024-03-21T19:37:36+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/monolog-bridge", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1" + "reference": "aaa40a0a6512976a6e07d5def7ce9476862ebd65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1", - "reference": "5d4f188e60d1e38a1d9d4bb6fbbbc13111dff2b1", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/aaa40a0a6512976a6e07d5def7ce9476862ebd65", + "reference": "aaa40a0a6512976a6e07d5def7ce9476862ebd65", "shasum": "" }, "require": { @@ -4337,7 +4426,7 @@ "description": "Provides integration for Monolog with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/monolog-bridge/tree/v7.0.3" + "source": "https://github.com/symfony/monolog-bridge/tree/v7.0.7" }, "funding": [ { @@ -4353,7 +4442,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/monolog-bundle", @@ -4438,16 +4527,16 @@ }, { "name": "symfony/notifier", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/notifier.git", - "reference": "515326dab227ecd3198b04df50edf949f7767a9a" + "reference": "1eeee1522fad108d7f094b1bf5453e5466e6f8fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/notifier/zipball/515326dab227ecd3198b04df50edf949f7767a9a", - "reference": "515326dab227ecd3198b04df50edf949f7767a9a", + "url": "https://api.github.com/repos/symfony/notifier/zipball/1eeee1522fad108d7f094b1bf5453e5466e6f8fc", + "reference": "1eeee1522fad108d7f094b1bf5453e5466e6f8fc", "shasum": "" }, "require": { @@ -4496,7 +4585,7 @@ "notifier" ], "support": { - "source": "https://github.com/symfony/notifier/tree/v7.0.3" + "source": "https://github.com/symfony/notifier/tree/v7.0.7" }, "funding": [ { @@ -4512,20 +4601,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.0.0", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "700ff4096e346f54cb628ea650767c8130f1001f" + "reference": "23cc173858776ad451e31f053b1c9f47840b2cfa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f", - "reference": "700ff4096e346f54cb628ea650767c8130f1001f", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/23cc173858776ad451e31f053b1c9f47840b2cfa", + "reference": "23cc173858776ad451e31f053b1c9f47840b2cfa", "shasum": "" }, "require": { @@ -4563,7 +4652,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.0.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.0.7" }, "funding": [ { @@ -4579,20 +4668,20 @@ "type": "tidelift" } ], - "time": "2023-08-08T10:20:21+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/password-hasher", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "0eba656c16ecdf5588b3ddd2b2337b06173d839f" + "reference": "5148b049248935f8a7b0a392aece2f22e9a1803d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/0eba656c16ecdf5588b3ddd2b2337b06173d839f", - "reference": "0eba656c16ecdf5588b3ddd2b2337b06173d839f", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/5148b049248935f8a7b0a392aece2f22e9a1803d", + "reference": "5148b049248935f8a7b0a392aece2f22e9a1803d", "shasum": "" }, "require": { @@ -4635,7 +4724,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v7.0.4" + "source": "https://github.com/symfony/password-hasher/tree/v7.0.7" }, "funding": [ { @@ -4651,7 +4740,7 @@ "type": "tidelift" } ], - "time": "2024-02-12T11:15:03+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -5219,16 +5308,16 @@ }, { "name": "symfony/process", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9" + "reference": "3839e56b94dd1dbd13235d27504e66baf23faba0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/0e7727191c3b71ebec6d529fa0e50a01ca5679e9", - "reference": "0e7727191c3b71ebec6d529fa0e50a01ca5679e9", + "url": "https://api.github.com/repos/symfony/process/zipball/3839e56b94dd1dbd13235d27504e66baf23faba0", + "reference": "3839e56b94dd1dbd13235d27504e66baf23faba0", "shasum": "" }, "require": { @@ -5260,7 +5349,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.0.4" + "source": "https://github.com/symfony/process/tree/v7.0.7" }, "funding": [ { @@ -5276,20 +5365,20 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/property-access", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "1c268ba954ccc5e78cf035b391abb67759e24423" + "reference": "8661b861480d2807eb2789ff99d034c0c71ab955" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/1c268ba954ccc5e78cf035b391abb67759e24423", - "reference": "1c268ba954ccc5e78cf035b391abb67759e24423", + "url": "https://api.github.com/repos/symfony/property-access/zipball/8661b861480d2807eb2789ff99d034c0c71ab955", + "reference": "8661b861480d2807eb2789ff99d034c0c71ab955", "shasum": "" }, "require": { @@ -5336,7 +5425,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v7.0.6" + "source": "https://github.com/symfony/property-access/tree/v7.0.7" }, "funding": [ { @@ -5352,20 +5441,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:57:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/property-info", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "b8844ddce7d53f78b57ec9be59da80fceddf3167" + "reference": "f0bdb46e19ab308527b324b7ec36161f6880a532" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/b8844ddce7d53f78b57ec9be59da80fceddf3167", - "reference": "b8844ddce7d53f78b57ec9be59da80fceddf3167", + "url": "https://api.github.com/repos/symfony/property-info/zipball/f0bdb46e19ab308527b324b7ec36161f6880a532", + "reference": "f0bdb46e19ab308527b324b7ec36161f6880a532", "shasum": "" }, "require": { @@ -5419,7 +5508,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v7.0.6" + "source": "https://github.com/symfony/property-info/tree/v7.0.7" }, "funding": [ { @@ -5435,20 +5524,20 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/proxy-manager-bridge", - "version": "v6.4.6", + "version": "v6.4.7", "source": { "type": "git", "url": "https://github.com/symfony/proxy-manager-bridge.git", - "reference": "1d67cac97e3a4987ffadec3faf9e6b8c00cf12cc" + "reference": "9352e4c11174eabb11e4732745a0278c217eb254" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/1d67cac97e3a4987ffadec3faf9e6b8c00cf12cc", - "reference": "1d67cac97e3a4987ffadec3faf9e6b8c00cf12cc", + "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/9352e4c11174eabb11e4732745a0278c217eb254", + "reference": "9352e4c11174eabb11e4732745a0278c217eb254", "shasum": "" }, "require": { @@ -5486,7 +5575,7 @@ "description": "Provides integration for ProxyManager with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/proxy-manager-bridge/tree/v6.4.6" + "source": "https://github.com/symfony/proxy-manager-bridge/tree/v6.4.7" }, "funding": [ { @@ -5502,20 +5591,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:56:30+00:00" + "time": "2024-04-18T09:22:46+00:00" }, { "name": "symfony/routing", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "cded64e5bbf9f31786f1055fcc76718fdd77519c" + "reference": "9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/cded64e5bbf9f31786f1055fcc76718fdd77519c", - "reference": "cded64e5bbf9f31786f1055fcc76718fdd77519c", + "url": "https://api.github.com/repos/symfony/routing/zipball/9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b", + "reference": "9f82bf7766ccc9c22ab7aeb9bebb98351483fa5b", "shasum": "" }, "require": { @@ -5567,7 +5656,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.0.6" + "source": "https://github.com/symfony/routing/tree/v7.0.7" }, "funding": [ { @@ -5583,20 +5672,20 @@ "type": "tidelift" } ], - "time": "2024-03-28T21:02:11+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/runtime", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5" + "reference": "e120730ef206b31bb5521b1a2389c058adbba9c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/ef2c2fd4b40fb8cd22221154399ad8888e81cdb5", - "reference": "ef2c2fd4b40fb8cd22221154399ad8888e81cdb5", + "url": "https://api.github.com/repos/symfony/runtime/zipball/e120730ef206b31bb5521b1a2389c058adbba9c7", + "reference": "e120730ef206b31bb5521b1a2389c058adbba9c7", "shasum": "" }, "require": { @@ -5646,7 +5735,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v7.0.3" + "source": "https://github.com/symfony/runtime/tree/v7.0.7" }, "funding": [ { @@ -5662,20 +5751,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/security-bundle", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "96a9e4eaf76514674d8ffd6127d8ec1204b72e7f" + "reference": "8d11101574ce8e2147a04245f4b968911a43ffd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/96a9e4eaf76514674d8ffd6127d8ec1204b72e7f", - "reference": "96a9e4eaf76514674d8ffd6127d8ec1204b72e7f", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/8d11101574ce8e2147a04245f4b968911a43ffd5", + "reference": "8d11101574ce8e2147a04245f4b968911a43ffd5", "shasum": "" }, "require": { @@ -5757,7 +5846,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v7.0.6" + "source": "https://github.com/symfony/security-bundle/tree/v7.0.7" }, "funding": [ { @@ -5773,20 +5862,20 @@ "type": "tidelift" } ], - "time": "2024-03-15T12:53:12+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/security-core", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "72b9d961a5dcd21e6bc29b99df51a9000a15dde0" + "reference": "6af8ac3b4d9c41a0ce0a4e33d532ba2000b47348" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/72b9d961a5dcd21e6bc29b99df51a9000a15dde0", - "reference": "72b9d961a5dcd21e6bc29b99df51a9000a15dde0", + "url": "https://api.github.com/repos/symfony/security-core/zipball/6af8ac3b4d9c41a0ce0a4e33d532ba2000b47348", + "reference": "6af8ac3b4d9c41a0ce0a4e33d532ba2000b47348", "shasum": "" }, "require": { @@ -5841,7 +5930,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v7.0.3" + "source": "https://github.com/symfony/security-core/tree/v7.0.7" }, "funding": [ { @@ -5857,20 +5946,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/security-csrf", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "f0f724e599f069b768e335e4bdf795726c7dfe8e" + "reference": "671d6736736555309991457dd877e7f6f3317d08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/f0f724e599f069b768e335e4bdf795726c7dfe8e", - "reference": "f0f724e599f069b768e335e4bdf795726c7dfe8e", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/671d6736736555309991457dd877e7f6f3317d08", + "reference": "671d6736736555309991457dd877e7f6f3317d08", "shasum": "" }, "require": { @@ -5909,7 +5998,7 @@ "description": "Symfony Security Component - CSRF Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-csrf/tree/v7.0.3" + "source": "https://github.com/symfony/security-csrf/tree/v7.0.7" }, "funding": [ { @@ -5925,20 +6014,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/security-http", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "f3a70a937128f47366821a9f4b5dbfaa0ba9c862" + "reference": "836a338f51cd46d57e77fcba61c6f8c6111a3717" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/f3a70a937128f47366821a9f4b5dbfaa0ba9c862", - "reference": "f3a70a937128f47366821a9f4b5dbfaa0ba9c862", + "url": "https://api.github.com/repos/symfony/security-http/zipball/836a338f51cd46d57e77fcba61c6f8c6111a3717", + "reference": "836a338f51cd46d57e77fcba61c6f8c6111a3717", "shasum": "" }, "require": { @@ -5996,7 +6085,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v7.0.4" + "source": "https://github.com/symfony/security-http/tree/v7.0.7" }, "funding": [ { @@ -6012,20 +6101,20 @@ "type": "tidelift" } ], - "time": "2024-02-26T07:52:39+00:00" + "time": "2024-04-19T13:26:52+00:00" }, { "name": "symfony/serializer", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "dbdc0c04c28ac53de1fa35f92fca26e9b1345d98" + "reference": "08f0c517acf4b12dfc0d3963cd12f7b8023aea31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/dbdc0c04c28ac53de1fa35f92fca26e9b1345d98", - "reference": "dbdc0c04c28ac53de1fa35f92fca26e9b1345d98", + "url": "https://api.github.com/repos/symfony/serializer/zipball/08f0c517acf4b12dfc0d3963cd12f7b8023aea31", + "reference": "08f0c517acf4b12dfc0d3963cd12f7b8023aea31", "shasum": "" }, "require": { @@ -6091,7 +6180,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v7.0.6" + "source": "https://github.com/symfony/serializer/tree/v7.0.7" }, "funding": [ { @@ -6107,7 +6196,7 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/service-contracts", @@ -6193,16 +6282,16 @@ }, { "name": "symfony/stopwatch", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112" + "reference": "41a7a24aa1dc82adf46a06bc292d1923acfe6b84" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/983900d6fddf2b0cbaacacbbad07610854bd8112", - "reference": "983900d6fddf2b0cbaacacbbad07610854bd8112", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/41a7a24aa1dc82adf46a06bc292d1923acfe6b84", + "reference": "41a7a24aa1dc82adf46a06bc292d1923acfe6b84", "shasum": "" }, "require": { @@ -6235,7 +6324,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.0.3" + "source": "https://github.com/symfony/stopwatch/tree/v7.0.7" }, "funding": [ { @@ -6251,20 +6340,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/string", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b" + "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f5832521b998b0bec40bee688ad5de98d4cf111b", - "reference": "f5832521b998b0bec40bee688ad5de98d4cf111b", + "url": "https://api.github.com/repos/symfony/string/zipball/e405b5424dc2528e02e31ba26b83a79fd4eb8f63", + "reference": "e405b5424dc2528e02e31ba26b83a79fd4eb8f63", "shasum": "" }, "require": { @@ -6321,7 +6410,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.0.4" + "source": "https://github.com/symfony/string/tree/v7.0.7" }, "funding": [ { @@ -6337,20 +6426,20 @@ "type": "tidelift" } ], - "time": "2024-02-01T13:17:36+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/translation", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "5b75e872f7d135d7abb4613809fadc8d9f3d30a0" + "reference": "1515e03afaa93e6419aba5d5c9d209159317100b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/5b75e872f7d135d7abb4613809fadc8d9f3d30a0", - "reference": "5b75e872f7d135d7abb4613809fadc8d9f3d30a0", + "url": "https://api.github.com/repos/symfony/translation/zipball/1515e03afaa93e6419aba5d5c9d209159317100b", + "reference": "1515e03afaa93e6419aba5d5c9d209159317100b", "shasum": "" }, "require": { @@ -6415,7 +6504,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.0.4" + "source": "https://github.com/symfony/translation/tree/v7.0.7" }, "funding": [ { @@ -6431,7 +6520,7 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/translation-contracts", @@ -6513,16 +6602,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "1d5745dac2e043553177a3b88a76b99c2a2f6c2e" + "reference": "214237f7b3b82eeb430e85ea415c4a2915c304f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/1d5745dac2e043553177a3b88a76b99c2a2f6c2e", - "reference": "1d5745dac2e043553177a3b88a76b99c2a2f6c2e", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/214237f7b3b82eeb430e85ea415c4a2915c304f6", + "reference": "214237f7b3b82eeb430e85ea415c4a2915c304f6", "shasum": "" }, "require": { @@ -6601,7 +6690,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v7.0.6" + "source": "https://github.com/symfony/twig-bridge/tree/v7.0.7" }, "funding": [ { @@ -6617,20 +6706,20 @@ "type": "tidelift" } ], - "time": "2024-03-28T21:02:11+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/twig-bundle", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "acab2368f53491e018bf31ef48b39df55a6812ef" + "reference": "4dd8a395b955045d031d9525a7149cfcee8d0b02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/acab2368f53491e018bf31ef48b39df55a6812ef", - "reference": "acab2368f53491e018bf31ef48b39df55a6812ef", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/4dd8a395b955045d031d9525a7149cfcee8d0b02", + "reference": "4dd8a395b955045d031d9525a7149cfcee8d0b02", "shasum": "" }, "require": { @@ -6685,7 +6774,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v7.0.4" + "source": "https://github.com/symfony/twig-bundle/tree/v7.0.7" }, "funding": [ { @@ -6701,20 +6790,20 @@ "type": "tidelift" } ], - "time": "2024-02-15T11:33:06+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/validator", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "a2df2c63b7944a162dee86ab8065f2f91b7d6e36" + "reference": "ab4e75b9d23ba70e78480aecbe4d8da15adf10eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/a2df2c63b7944a162dee86ab8065f2f91b7d6e36", - "reference": "a2df2c63b7944a162dee86ab8065f2f91b7d6e36", + "url": "https://api.github.com/repos/symfony/validator/zipball/ab4e75b9d23ba70e78480aecbe4d8da15adf10eb", + "reference": "ab4e75b9d23ba70e78480aecbe4d8da15adf10eb", "shasum": "" }, "require": { @@ -6779,7 +6868,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v7.0.6" + "source": "https://github.com/symfony/validator/tree/v7.0.7" }, "funding": [ { @@ -6795,20 +6884,20 @@ "type": "tidelift" } ], - "time": "2024-03-28T09:20:36+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb" + "reference": "d1627b66fd87c8b4d90cabe5671c29d575690924" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb", - "reference": "66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d1627b66fd87c8b4d90cabe5671c29d575690924", + "reference": "d1627b66fd87c8b4d90cabe5671c29d575690924", "shasum": "" }, "require": { @@ -6862,7 +6951,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.0.6" + "source": "https://github.com/symfony/var-dumper/tree/v7.0.7" }, "funding": [ { @@ -6878,20 +6967,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:57:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "c74c568d2a15a1d407cf40d61ea82bc2d521e27b" + "reference": "cdecc0022e40e90340ba1a59a3d5ccf069777078" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c74c568d2a15a1d407cf40d61ea82bc2d521e27b", - "reference": "c74c568d2a15a1d407cf40d61ea82bc2d521e27b", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/cdecc0022e40e90340ba1a59a3d5ccf069777078", + "reference": "cdecc0022e40e90340ba1a59a3d5ccf069777078", "shasum": "" }, "require": { @@ -6938,7 +7027,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.0.6" + "source": "https://github.com/symfony/var-exporter/tree/v7.0.7" }, "funding": [ { @@ -6954,20 +7043,20 @@ "type": "tidelift" } ], - "time": "2024-03-20T21:25:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/web-link", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/web-link.git", - "reference": "855a347feb2ecfc1d1a379c739aff956d4cbec00" + "reference": "19312f38543e77b09f04f374368b73530bfb9482" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-link/zipball/855a347feb2ecfc1d1a379c739aff956d4cbec00", - "reference": "855a347feb2ecfc1d1a379c739aff956d4cbec00", + "url": "https://api.github.com/repos/symfony/web-link/zipball/19312f38543e77b09f04f374368b73530bfb9482", + "reference": "19312f38543e77b09f04f374368b73530bfb9482", "shasum": "" }, "require": { @@ -7021,7 +7110,7 @@ "push" ], "support": { - "source": "https://github.com/symfony/web-link/tree/v7.0.3" + "source": "https://github.com/symfony/web-link/tree/v7.0.7" }, "funding": [ { @@ -7037,20 +7126,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/yaml", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "2d4fca631c00700597e9442a0b2451ce234513d3" + "reference": "0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/2d4fca631c00700597e9442a0b2451ce234513d3", - "reference": "2d4fca631c00700597e9442a0b2451ce234513d3", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c", + "reference": "0d3916ae69ea28b59d94b60c4f2b50f4e25adb5c", "shasum": "" }, "require": { @@ -7092,7 +7181,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.0.3" + "source": "https://github.com/symfony/yaml/tree/v7.0.7" }, "funding": [ { @@ -7108,38 +7197,38 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-28T11:44:19+00:00" }, { "name": "twig/extra-bundle", - "version": "v3.8.0", + "version": "v3.9.3", "source": { "type": "git", "url": "https://github.com/twigphp/twig-extra-bundle.git", - "reference": "32807183753de0388c8e59f7ac2d13bb47311140" + "reference": "ef6869adf1fdab66f7e495771a7ba01496ffc0d5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/32807183753de0388c8e59f7ac2d13bb47311140", - "reference": "32807183753de0388c8e59f7ac2d13bb47311140", + "url": "https://api.github.com/repos/twigphp/twig-extra-bundle/zipball/ef6869adf1fdab66f7e495771a7ba01496ffc0d5", + "reference": "ef6869adf1fdab66f7e495771a7ba01496ffc0d5", "shasum": "" }, "require": { "php": ">=7.2.5", - "symfony/framework-bundle": "^5.4|^6.0|^7.0", - "symfony/twig-bundle": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^5.4|^6.4|^7.0", + "symfony/twig-bundle": "^5.4|^6.4|^7.0", "twig/twig": "^3.0" }, "require-dev": { "league/commonmark": "^1.0|^2.0", "symfony/phpunit-bridge": "^6.4|^7.0", "twig/cache-extra": "^3.0", - "twig/cssinliner-extra": "^2.12|^3.0", - "twig/html-extra": "^2.12|^3.0", - "twig/inky-extra": "^2.12|^3.0", - "twig/intl-extra": "^2.12|^3.0", - "twig/markdown-extra": "^2.12|^3.0", - "twig/string-extra": "^2.12|^3.0" + "twig/cssinliner-extra": "^3.0", + "twig/html-extra": "^3.0", + "twig/inky-extra": "^3.0", + "twig/intl-extra": "^3.0", + "twig/markdown-extra": "^3.0", + "twig/string-extra": "^3.0" }, "type": "symfony-bundle", "autoload": { @@ -7170,7 +7259,7 @@ "twig" ], "support": { - "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.8.0" + "source": "https://github.com/twigphp/twig-extra-bundle/tree/v3.9.3" }, "funding": [ { @@ -7182,34 +7271,41 @@ "type": "tidelift" } ], - "time": "2023-11-21T14:02:01+00:00" + "time": "2024-04-18T09:24:21+00:00" }, { "name": "twig/twig", - "version": "v3.8.0", + "version": "v3.9.3", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d" + "reference": "a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", - "reference": "9d15f0ac07f44dc4217883ec6ae02fd555c6f71d", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58", + "reference": "a842d75fed59cdbcbd3a3ad7fb9eb768fc350d58", "shasum": "" }, "require": { "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", "symfony/polyfill-mbstring": "^1.3", "symfony/polyfill-php80": "^1.22" }, "require-dev": { "psr/container": "^1.0|^2.0", - "symfony/phpunit-bridge": "^5.4.9|^6.3|^7.0" + "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, "type": "library", "autoload": { + "files": [ + "src/Resources/core.php", + "src/Resources/debug.php", + "src/Resources/escaper.php", + "src/Resources/string_loader.php" + ], "psr-4": { "Twig\\": "src/" } @@ -7242,7 +7338,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.8.0" + "source": "https://github.com/twigphp/Twig/tree/v3.9.3" }, "funding": [ { @@ -7254,7 +7350,7 @@ "type": "tidelift" } ], - "time": "2023-11-21T18:54:41+00:00" + "time": "2024-04-18T11:59:33+00:00" }, { "name": "webmozart/assert", @@ -8211,6 +8307,61 @@ ], "time": "2024-04-05T04:35:58+00:00" }, + { + "name": "qossmic/deptrac-shim", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/qossmic/deptrac-shim.git", + "reference": "3179a2c4978654add865309e3c280ef3d60f0043" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/qossmic/deptrac-shim/zipball/3179a2c4978654add865309e3c280ef3d60f0043", + "reference": "3179a2c4978654add865309e3c280ef3d60f0043", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "ext-zlib": "*", + "php": "^8.1" + }, + "replace": { + "qossmic/deptrac": "self.version" + }, + "suggest": { + "ext-dom": "For using the JUnit output formatter" + }, + "bin": [ + "deptrac" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tim Glabisch" + }, + { + "name": "Simon Mönch", + "email": "simon.moench@qossmic.com" + }, + { + "name": "Denis Brumann", + "email": "denis.brumann@qossmic.com", + "role": "maintainer" + } + ], + "description": "deptrac phar distribution", + "support": { + "issues": "https://github.com/qossmic/deptrac-shim/issues", + "source": "https://github.com/qossmic/deptrac-shim/tree/1.0.2" + }, + "time": "2022-12-02T11:47:53+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.2", @@ -9176,16 +9327,16 @@ }, { "name": "symfony/browser-kit", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "725d5b15681685ac17b20b575254c75639722488" + "reference": "0a48e67a7975c07d8cc0661fbbdddce56c58425e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/725d5b15681685ac17b20b575254c75639722488", - "reference": "725d5b15681685ac17b20b575254c75639722488", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/0a48e67a7975c07d8cc0661fbbdddce56c58425e", + "reference": "0a48e67a7975c07d8cc0661fbbdddce56c58425e", "shasum": "" }, "require": { @@ -9224,7 +9375,7 @@ "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/v7.0.3" + "source": "https://github.com/symfony/browser-kit/tree/v7.0.7" }, "funding": [ { @@ -9240,20 +9391,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/css-selector", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ec60a4edf94e63b0556b6a0888548bb400a3a3be" + "reference": "b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ec60a4edf94e63b0556b6a0888548bb400a3a3be", - "reference": "ec60a4edf94e63b0556b6a0888548bb400a3a3be", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc", + "reference": "b08a4ad89e84b29cec285b7b1f781a7ae51cf4bc", "shasum": "" }, "require": { @@ -9289,7 +9440,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.0.3" + "source": "https://github.com/symfony/css-selector/tree/v7.0.7" }, "funding": [ { @@ -9305,20 +9456,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/debug-bundle", - "version": "v7.0.3", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "b0db5c443883ce5c10c2265c77feb9833c3d9d6d" + "reference": "4b013a2c886cfd0292d90a9a9cebfa29ec7b578c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/b0db5c443883ce5c10c2265c77feb9833c3d9d6d", - "reference": "b0db5c443883ce5c10c2265c77feb9833c3d9d6d", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/4b013a2c886cfd0292d90a9a9cebfa29ec7b578c", + "reference": "4b013a2c886cfd0292d90a9a9cebfa29ec7b578c", "shasum": "" }, "require": { @@ -9363,7 +9514,7 @@ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v7.0.3" + "source": "https://github.com/symfony/debug-bundle/tree/v7.0.7" }, "funding": [ { @@ -9379,20 +9530,20 @@ "type": "tidelift" } ], - "time": "2024-01-23T15:02:46+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/dom-crawler", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "6cb272cbec4dc7a30a853d2931766b03bea92dda" + "reference": "7cb4ae7166a8a36916be390dbb3819474fb06a29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/6cb272cbec4dc7a30a853d2931766b03bea92dda", - "reference": "6cb272cbec4dc7a30a853d2931766b03bea92dda", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/7cb4ae7166a8a36916be390dbb3819474fb06a29", + "reference": "7cb4ae7166a8a36916be390dbb3819474fb06a29", "shasum": "" }, "require": { @@ -9430,7 +9581,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v7.0.4" + "source": "https://github.com/symfony/dom-crawler/tree/v7.0.7" }, "funding": [ { @@ -9446,20 +9597,20 @@ "type": "tidelift" } ], - "time": "2024-02-12T11:15:03+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/maker-bundle", - "version": "v1.58.0", + "version": "v1.59.0", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "c4f8d2c5d55950e1a49e822efc83a8511bee8a36" + "reference": "1f02b59b98003b2c1f51bc8f178aee5cbf36779c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/c4f8d2c5d55950e1a49e822efc83a8511bee8a36", - "reference": "c4f8d2c5d55950e1a49e822efc83a8511bee8a36", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/1f02b59b98003b2c1f51bc8f178aee5cbf36779c", + "reference": "1f02b59b98003b2c1f51bc8f178aee5cbf36779c", "shasum": "" }, "require": { @@ -9522,7 +9673,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.58.0" + "source": "https://github.com/symfony/maker-bundle/tree/v1.59.0" }, "funding": [ { @@ -9538,20 +9689,20 @@ "type": "tidelift" } ], - "time": "2024-04-06T15:08:12+00:00" + "time": "2024-04-27T21:12:25+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v7.0.6", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "a014167aa1f66cb9990675840da65609d3e61612" + "reference": "0a0b90ba08b9a03e09ad49f8d613bdf3eca3a7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/a014167aa1f66cb9990675840da65609d3e61612", - "reference": "a014167aa1f66cb9990675840da65609d3e61612", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/0a0b90ba08b9a03e09ad49f8d613bdf3eca3a7a9", + "reference": "0a0b90ba08b9a03e09ad49f8d613bdf3eca3a7a9", "shasum": "" }, "require": { @@ -9603,7 +9754,7 @@ "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.6" + "source": "https://github.com/symfony/phpunit-bridge/tree/v7.0.7" }, "funding": [ { @@ -9619,20 +9770,20 @@ "type": "tidelift" } ], - "time": "2024-03-19T11:57:22+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v7.0.4", + "version": "v7.0.7", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "542daea1345fe181cbfd52db00717174a838ea0a" + "reference": "a9a722210b391d7f6d97f140a5f2f7eee604d81a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/542daea1345fe181cbfd52db00717174a838ea0a", - "reference": "542daea1345fe181cbfd52db00717174a838ea0a", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/a9a722210b391d7f6d97f140a5f2f7eee604d81a", + "reference": "a9a722210b391d7f6d97f140a5f2f7eee604d81a", "shasum": "" }, "require": { @@ -9684,7 +9835,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.0.4" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v7.0.7" }, "funding": [ { @@ -9700,7 +9851,7 @@ "type": "tidelift" } ], - "time": "2024-02-22T20:27:20+00:00" + "time": "2024-04-18T09:29:19+00:00" }, { "name": "theseer/tokenizer", @@ -9764,5 +9915,5 @@ "ext-iconv": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/config/doctrine/orm/Dinosaur.orm.xml b/config/doctrine/orm/Dinosaur.orm.xml index 2dd902f..7ea4376 100644 --- a/config/doctrine/orm/Dinosaur.orm.xml +++ b/config/doctrine/orm/Dinosaur.orm.xml @@ -5,8 +5,8 @@ https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> @@ -21,7 +21,7 @@ diff --git a/config/doctrine/orm/Species.orm.xml b/config/doctrine/orm/Species.orm.xml index 100370d..82ceb82 100644 --- a/config/doctrine/orm/Species.orm.xml +++ b/config/doctrine/orm/Species.orm.xml @@ -5,8 +5,8 @@ https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> @@ -20,7 +20,7 @@ diff --git a/config/doctrine/orm/User.orm.xml b/config/doctrine/orm/User.orm.xml index 75c3f08..90153ad 100644 --- a/config/doctrine/orm/User.orm.xml +++ b/config/doctrine/orm/User.orm.xml @@ -4,7 +4,11 @@ xsi:schemaLocation="https://doctrine-project.org/schemas/orm/doctrine-mapping https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - + diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index d62f81c..ee8d1b7 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -24,8 +24,8 @@ doctrine: is_bundle: false type: xml dir: '%kernel.project_dir%/config/doctrine/orm' - prefix: 'App\Entity' - alias: App + prefix: 'Domain\Model' + alias: Domain when@test: doctrine: diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml new file mode 100644 index 0000000..5386421 --- /dev/null +++ b/config/packages/messenger.yaml @@ -0,0 +1,21 @@ +framework: + messenger: + default_bus: command.bus + transports: + sync: 'sync://' + + buses: + command.bus: + default_middleware: true + middleware: + - Infrastructure\Symfony\Messenger\Middleware\DomainEventDispatcher + - dispatch_after_current_bus + - doctrine_transaction + + query.bus: ~ + + event.bus: + default_middleware: allow_no_handlers + middleware: + - dispatch_after_current_bus + - doctrine_transaction \ No newline at end of file diff --git a/config/packages/security.yaml b/config/packages/security.yaml index abafd7f..a1e30dd 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -4,9 +4,7 @@ security: providers: app_user_provider: - entity: - class: App\Entity\User - property: email + id: Application\Security\UserProvider role_hierarchy: ROLE_ADMIN: ROLE_USER @@ -31,10 +29,10 @@ security: access_control: - { path: ^/dinosaurs$, roles: ROLE_USER } - { path: ^/dinosaurs/\d+$, roles: ROLE_USER } - - { path: ^/dinosaurs/, roles: ROLE_ADMIN } + # - { path: ^/dinosaurs/, roles: ROLE_ADMIN } - { path: ^/species$, roles: ROLE_USER } - { path: ^/species/\d+$, roles: ROLE_USER } - - { path: ^/species/, roles: ROLE_ADMIN } + # - { path: ^/species/, roles: ROLE_ADMIN } # - { path: ^/admin, roles: ROLE_ADMIN } # - { path: ^/profile, roles: ROLE_USER } diff --git a/config/routes.yaml b/config/routes.yaml index 9286e81..17a5790 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -1,3 +1,3 @@ controllers: - resource: ../src/Controller/ + resource: ../src/Application/Controller/ type: attribute diff --git a/config/services.yaml b/config/services.yaml index 1d3246d..986a486 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -1,8 +1,4 @@ -# This file is the entry point to configure your own services. -# Files in the packages/ subdirectory configure your dependencies. - -# Put parameters here that don't need to change on each machine where the app is deployed -# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration +--- parameters: env(MYSQL_HOST): '%env(resolve:MYSQL_HOST)%' env(MYSQL_DATABASE): '%env(resolve:MYSQL_DATABASE)%' @@ -10,19 +6,14 @@ parameters: env(MYSQL_PASSWORD): '%env(resolve:MYSQL_PASSWORD)%' services: - # default configuration for services in *this* file _defaults: - autowire: true # Automatically injects dependencies in your services. - autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. + autowire: true + autoconfigure: true - # makes classes in src/ available to be used as services - # this creates a service per class whose id is the fully-qualified class name - App\: - resource: '../src/' + Application\: + resource: '../src/Application/' exclude: - - '../src/DependencyInjection/' - - '../src/Entity/' - - '../src/Kernel.php' + - '../src/Application/DomainEventsHandler/' - # add more service definitions when explicit configuration is needed - # please note that last definitions always *replace* previous ones + Infrastructure\Doctrine\DataFixtures\: + resource: '../src/Infrastructure/Doctrine/DataFixtures/**.php' diff --git a/config/services/doctrine_event_listeners.yaml b/config/services/doctrine_event_listeners.yaml new file mode 100644 index 0000000..13ccdb0 --- /dev/null +++ b/config/services/doctrine_event_listeners.yaml @@ -0,0 +1,11 @@ +--- +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Infrastructure\Doctrine\EventListener\HashUserPasswordListener: + tags: + - { name: doctrine.event_listener, event: prePersist } + - { name: doctrine.event_listener, event: preUpdate } diff --git a/config/services/domain_events.yaml b/config/services/domain_events.yaml new file mode 100644 index 0000000..952b1b6 --- /dev/null +++ b/config/services/domain_events.yaml @@ -0,0 +1,13 @@ +--- +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Domain\EventsRegisterer: ~ + + Application\DomainEventsHandler\: + resource: '%kernel.project_dir%/src/Application/DomainEventsHandler/**.php' + tags: + - { name: messenger.message_handler, bus: event.bus } diff --git a/config/services/messenger.yaml b/config/services/messenger.yaml new file mode 100644 index 0000000..d234e70 --- /dev/null +++ b/config/services/messenger.yaml @@ -0,0 +1,27 @@ +--- +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Infrastructure\Symfony\Messenger\Middleware\: + resource: '%kernel.project_dir%/src/Infrastructure/Symfony/Messenger/Middleware/**.php' + + Infrastructure\Symfony\Messenger\CommandBus: + $messageBus: '@command.bus' + + Application\MessageBus\CommandBus: + alias: Infrastructure\Symfony\Messenger\CommandBus + + Infrastructure\Symfony\Messenger\QueryBus: + $messageBus: '@query.bus' + + Application\MessageBus\QueryBus: + alias: Infrastructure\Symfony\Messenger\QueryBus + + Infrastructure\Symfony\Messenger\EventBus: + $messageBus: '@event.bus' + + Application\MessageBus\EventBus: + alias: Infrastructure\Symfony\Messenger\EventBus \ No newline at end of file diff --git a/config/services/queries.yaml b/config/services/queries.yaml new file mode 100644 index 0000000..a52136c --- /dev/null +++ b/config/services/queries.yaml @@ -0,0 +1,11 @@ +--- +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Domain\Query\: + resource: '%kernel.project_dir%/src/Domain/Query/**/Handler.php' + tags: + - { name: messenger.message_handler, bus: query.bus } diff --git a/config/services/repositories.yaml b/config/services/repositories.yaml new file mode 100644 index 0000000..7d7541e --- /dev/null +++ b/config/services/repositories.yaml @@ -0,0 +1,17 @@ +--- +services: + _defaults: + autowire: true + autoconfigure: true + + Infrastructure\Doctrine\Repository\: + resource: '%kernel.project_dir%/src/Infrastructure/Doctrine/Repository/*' + + Domain\Collection\DinosaursCollection: + alias: Infrastructure\Doctrine\Repository\DinosaurRepository + + Domain\Collection\SpeciesCollection: + alias: Infrastructure\Doctrine\Repository\SpeciesRepository + + Domain\Collection\UsersCollection: + alias: Infrastructure\Doctrine\Repository\UserRepository \ No newline at end of file diff --git a/config/services/use_cases.yaml b/config/services/use_cases.yaml new file mode 100644 index 0000000..f462146 --- /dev/null +++ b/config/services/use_cases.yaml @@ -0,0 +1,11 @@ +--- +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Domain\UseCase\: + resource: '%kernel.project_dir%/src/Domain/UseCase/**/Handler.php' + tags: + - { name: messenger.message_handler, bus: command.bus } diff --git a/deptrac.yaml b/deptrac.yaml new file mode 100644 index 0000000..5dab126 --- /dev/null +++ b/deptrac.yaml @@ -0,0 +1,39 @@ +--- +parameters: + paths: + - ./src + layers: + - name: Application + collectors: + - type: classLike + regex: ^Application\\.* + - name: Domain + collectors: + - type: classLike + regex: ^Domain\\.* + - name: Infrastructure + collectors: + - type: classLike + regex: ^Infrastructure\\.* + - name: Framework + collectors: + - type: classLike + regex: ^Symfony\\.* + - name: Kernel + collectors: + - type: classLike + regex: ^App\\Kernel.php + - name: Others + collectors: + - type: classLike + regex: ^(Doctrine)\\.* + ruleset: + Infrastructure: + - +Application + - Others + Application: + - Domain + - Framework + Domain: ~ + Kernel: + - Framework \ No newline at end of file diff --git a/src/Controller/AuthenticationController.php b/src/Application/Controller/AuthenticationController.php similarity index 56% rename from src/Controller/AuthenticationController.php rename to src/Application/Controller/AuthenticationController.php index ce41acd..910e337 100644 --- a/src/Controller/AuthenticationController.php +++ b/src/Application/Controller/AuthenticationController.php @@ -2,10 +2,13 @@ declare(strict_types=1); -namespace App\Controller; +namespace Application\Controller; -use App\Form\Type\UserType; -use Doctrine\Persistence\ManagerRegistry; +use Application\Form\Type\UserType; +use Application\MessageBus\CommandBus; +use Domain\Collection\UsersCollection; +use Domain\Exception\UserAlreadyExistsException; +use Domain\UseCase\RegisterUser\Input; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -14,8 +17,14 @@ final class AuthenticationController extends AbstractController { + public function __construct( + private readonly UsersCollection $usersCollection, + private readonly CommandBus $commandBus + ) { + } + #[Route('/register', name: 'register')] - public function register(Request $request, ManagerRegistry $doctrine): Response + public function register(Request $request): Response { $form = $this->createForm(UserType::class); @@ -24,13 +33,20 @@ public function register(Request $request, ManagerRegistry $doctrine): Response if ($form->isSubmitted() && $form->isValid()) { $user = $form->getData(); - $em = $doctrine->getManager(); - $em->persist($user); - $em->flush($user); + $input = new Input( + email: $user['email'], + password: $user['password'], + ); + + try { + $this->commandBus->dispatch($input); - $this->addFlash('success', 'You have been sucessfully registered!'); + $this->addFlash('success', 'You have been sucessfully registered!'); - return $this->redirectToRoute('login'); + return $this->redirectToRoute('login'); + } catch (UserAlreadyExistsException $e) { + $this->addFlash('danger', 'The email is already in use.'); + } } return $this->render('register.html.twig', [ diff --git a/src/Application/Controller/DinosaursController.php b/src/Application/Controller/DinosaursController.php new file mode 100644 index 0000000..8ad107f --- /dev/null +++ b/src/Application/Controller/DinosaursController.php @@ -0,0 +1,164 @@ +createForm(SearchType::class); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $search = $form->getData(); + + $q = $search['q']; + } + + $dinosaurs = $this->queryBus->dispatch(new GetAllDinosaurs\Query($q)); + + return $this->render('dinosaurs-list.html.twig', [ + 'dinosaurs' => $dinosaurs, + 'searchForm' => $form->createView(), + ]); + } + + #[Route( + '/dinosaurs/{id}', + name: 'app_single_dinosaur', + requirements: ['id' => '\d+'] + )] + public function single(string $id): Response + { + try { + $dinosaur = $this->queryBus->dispatch(new GetSingleDinosaur\Query($id)); + } catch (DinosaurNotFoundException $e) { + throw $this->createNotFoundException(); + } + + return $this->render('dinosaur.html.twig', [ + 'dinosaur' => $dinosaur, + ]); + } + + #[Route('/dinosaurs/create', name: 'app_create_dinosaur')] + public function create(Request $request): Response + { + $form = $this->createForm(DinosaurType::class); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $dinosaur = $form->getData(); + + $input = new CreateDinosaur\Input( + $dinosaur['name'], + $dinosaur['gender'], + $dinosaur['species']->getId(), + $dinosaur['age'], + $dinosaur['eyesColor'] + ); + + try { + $this->commandBus->dispatch($input); + + $this->addFlash('success', 'The dinosaur has been created!'); + + return $this->redirectToRoute('app_list_dinosaurs'); + } catch (DomainException $e) { + $this->addFlash('danger', $e->getMessage()); + } + } + + return $this->render('create-dinosaur.html.twig', [ + 'form' => $form, + ]); + } + + #[Route( + '/dinosaurs/{id}/edit', + name: 'app_edit_dinosaur', + requirements: ['id' => '\d+'] + )] + public function edit(Request $request, int $id): Response + { + try { + $dinosaur = $this->queryBus->dispatch(new GetSingleDinosaur\Query($id)); + } catch (DinosaurNotFoundException $e) { + throw $this->createNotFoundException( + 'The dinosaur you are looking for does not exists.' + ); + } + + $form = $this->createForm(DinosaurType::class, $dinosaur); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $dinosaur = $form->getData(); + + $input = EditDinosaur\Input::fromReadModel($dinosaur); + + try { + $this->commandBus->dispatch($input); + + $this->addFlash('success', 'The dinosaur has been updated!'); + + return $this->redirectToRoute('app_list_dinosaurs'); + } catch (DomainException $e) { + $this->addFlash('danger', $e->getMessage()); + } + } + + return $this->render('edit-dinosaur.html.twig', [ + 'form' => $form, + ]); + } + + #[Route( + '/dinosaurs/{id}/remove', + name: 'app_remove_dinosaur', + requirements: ['id' => '\d+'] + )] + public function remove(int $id): Response + { + $input = new RemoveDinosaur\Input($id); + + try { + $this->commandBus->dispatch($input); + + $this->addFlash('success', 'The dinosaur has been removed!'); + } catch (DomainException $e) { + $this->addFlash('danger', $e->getMessage()); + } + + return $this->redirectToRoute('app_list_dinosaurs'); + } +} diff --git a/src/Application/Controller/SpeciesController.php b/src/Application/Controller/SpeciesController.php new file mode 100644 index 0000000..dd49f09 --- /dev/null +++ b/src/Application/Controller/SpeciesController.php @@ -0,0 +1,130 @@ +queryBus->dispatch(new GetAllSpecies\Query()); + + return $this->render('species-list.html.twig', [ + 'speciesList' => $speciesList, + ]); + } + + #[Route('/species/create', name: 'app_create_species')] + public function create(Request $request): Response + { + $form = $this->createForm(SpeciesType::class); + + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $rawSpecies = $form->getData(); + + $input = new CreateSpecies\Input( + name: $rawSpecies['name'], + habitats: $rawSpecies['habitats'], + feeding: $rawSpecies['feeding'] + ); + + try { + $output = $this->commandBus->dispatch($input); + + $this->addFlash('success', 'The species has been created!'); + + return $this->redirectToRoute('app_list_species'); + } catch (SpeciesAlreadyExistsException $e) { + $this->addFlash('error', $e->getMessage()); + } + } + + return $this->render('create-species.html.twig', [ + 'form' => $form, + ]); + } + + #[Route( + '/species/{id}/edit', + name: 'app_edit_species', + requirements: ['id' => '\d+'] + )] + public function edit(Request $request, string $id): Response + { + try { + $species = $this->queryBus->dispatch(new GetSingleSpecies\Query($id)); + } catch (SpeciesNotFoundException $e) { + throw $this->createNotFoundException( + 'The species you are looking for does not exists.' + ); + } + + $form = $this->createForm(SpeciesType::class, $species); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $species = $form->getData(); + + $input = EditSpecies\Input::fromReadModel($species); + + try { + $this->commandBus->dispatch($input); + + $this->addFlash('success', 'The species has been updated!'); + + return $this->redirectToRoute('app_list_species'); + } catch (SpeciesAlreadyExistsException $e) { + $this->addFlash('error', $e->getMessage()); + } catch (SpeciesNotFoundException $e) { + throw $this->createNotFoundException($e->getMessage()); + } + } + + return $this->render('edit-species.html.twig', [ + 'form' => $form, + ]); + } + + #[Route( + '/species/{id}/remove', + name: 'app_remove_species', + requirements: ['id' => '\d+'] + )] + public function remove(string $id): Response + { + try { + $this->commandBus->dispatch(new RemoveSpecies\Input($id)); + } catch (SpeciesNotFoundException $e) { + throw $this->createNotFoundException($e->getMessage()); + } + + $this->addFlash('success', 'The species has been removed!'); + + return $this->redirectToRoute('app_list_species'); + } +} diff --git a/src/Application/DomainEventsHandler/LogWhenDinosaurDied.php b/src/Application/DomainEventsHandler/LogWhenDinosaurDied.php new file mode 100644 index 0000000..58735b8 --- /dev/null +++ b/src/Application/DomainEventsHandler/LogWhenDinosaurDied.php @@ -0,0 +1,26 @@ +logger->info(sprintf( + 'Dinosaur %s died', + $event->dinosaurName + )); + } +} diff --git a/src/Application/DomainEventsHandler/LogWhenDinosaurIsBorn.php b/src/Application/DomainEventsHandler/LogWhenDinosaurIsBorn.php new file mode 100644 index 0000000..9c1d27e --- /dev/null +++ b/src/Application/DomainEventsHandler/LogWhenDinosaurIsBorn.php @@ -0,0 +1,32 @@ +getAggregateRootId(); + + $dinosaur = $this->dinosaursCollection->find($dinosaurId); + + $this->logger->info(sprintf( + 'Dinosaur %s was born', + $dinosaur->getName() + )); + } +} diff --git a/src/Application/Form/DataTransformer/SpeciesReadToModel.php b/src/Application/Form/DataTransformer/SpeciesReadToModel.php new file mode 100644 index 0000000..79b2a76 --- /dev/null +++ b/src/Application/Form/DataTransformer/SpeciesReadToModel.php @@ -0,0 +1,45 @@ +getId(); + + $species = $this->speciesCollection->find($speciesId); + + if ($species === null) { + throw new SpeciesNotFoundException($speciesId); + } + + return $species; + } + + public function reverseTransform(mixed $value): mixed + { + if (!$value instanceof ModelSpecies) { + return $value; + } + + return new Species($value); + } +} diff --git a/src/Form/Type/DatalistType.php b/src/Application/Form/Type/DatalistType.php similarity index 95% rename from src/Form/Type/DatalistType.php rename to src/Application/Form/Type/DatalistType.php index a616c7f..474a290 100644 --- a/src/Form/Type/DatalistType.php +++ b/src/Application/Form/Type/DatalistType.php @@ -1,6 +1,6 @@ add('age', NumberType::class) ->add('eyesColor', ColorType::class) ->add('submit', SubmitType::class); - } - public function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'data_class' => Dinosaur::class, - 'empty_data' => function (FormInterface $form) { - return new Dinosaur( - $form->get('name')->getData(), - $form->get('gender')->getData(), - $form->get('species')->getData(), - $form->get('age')->getData(), - $form->get('eyesColor')->getData(), - ); - }, - ]); + $builder->get('species')->addModelTransformer($this->speciesReadToModel); } } diff --git a/src/Form/Type/SearchType.php b/src/Application/Form/Type/SearchType.php similarity index 94% rename from src/Form/Type/SearchType.php rename to src/Application/Form/Type/SearchType.php index f148212..f415ca3 100644 --- a/src/Form/Type/SearchType.php +++ b/src/Application/Form/Type/SearchType.php @@ -1,6 +1,6 @@ setDefaults([ - 'data_class' => Species::class, - 'empty_data' => function (FormInterface $form) { - return new Species( - $form->get('name')->getData(), - $form->get('habitats')->getData(), - $form->get('feeding')->getData(), - ); - }, + 'compound' => true, ]); } } diff --git a/src/Application/Form/Type/UserType.php b/src/Application/Form/Type/UserType.php new file mode 100644 index 0000000..2fe680b --- /dev/null +++ b/src/Application/Form/Type/UserType.php @@ -0,0 +1,24 @@ +add('email', EmailType::class) + ->add('password', PasswordType::class) + ->add('submit', SubmitType::class, [ + 'label' => 'Register', + ]); + } +} diff --git a/src/Application/MessageBus/CommandBus.php b/src/Application/MessageBus/CommandBus.php new file mode 100644 index 0000000..dfb6aff --- /dev/null +++ b/src/Application/MessageBus/CommandBus.php @@ -0,0 +1,10 @@ +user->getRoles(); + } + + public function eraseCredentials(): void + { + } + + public function getUserIdentifier(): string + { + return $this->user->getEmail(); + } + + public function getPassword(): ?string + { + return $this->user->getPassword(); + } +} diff --git a/src/Application/Security/UserProvider.php b/src/Application/Security/UserProvider.php new file mode 100644 index 0000000..abf82a8 --- /dev/null +++ b/src/Application/Security/UserProvider.php @@ -0,0 +1,41 @@ +users->findOneByEmail($identifier); + + if (null === $user) { + throw new UserNotFoundException(); + } + + return new User($user); + } + + public function refreshUser(UserInterface $user): UserInterface + { + return $this->loadUserByIdentifier( + $user->getUserIdentifier() + ); + } + + public function supportsClass($class): bool + { + return User::class === $class; + } +} diff --git a/src/Controller/.gitignore b/src/Controller/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/src/Controller/DinosaursController.php b/src/Controller/DinosaursController.php deleted file mode 100644 index 4ced07c..0000000 --- a/src/Controller/DinosaursController.php +++ /dev/null @@ -1,142 +0,0 @@ -createForm(SearchType::class); - - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $search = $form->getData(); - - $q = $search['q']; - } - - $dinosaurs = $doctrine - ->getRepository(Dinosaur::class) - ->search($q); - - return $this->render('dinosaurs-list.html.twig', [ - 'dinosaurs' => $dinosaurs, - 'searchForm' => $form->createView(), - ]); - } - - #[Route( - '/dinosaurs/{id}', - name: 'app_single_dinosaur', - requirements: ['id' => '\d+'] - )] - public function single(string $id, ManagerRegistry $doctrine): Response - { - $dinosaur = $doctrine - ->getRepository(Dinosaur::class) - ->find($id); - - if (false === $dinosaur) { - throw $this->createNotFoundException('The dinosaur you are looking for does not exists.'); - } - - return $this->render('dinosaur.html.twig', [ - 'dinosaur' => $dinosaur, - ]); - } - - #[Route('/dinosaurs/create', name: 'app_create_dinosaur')] - public function create(Request $request, ManagerRegistry $doctrine): Response - { - $form = $this->createForm(DinosaurType::class); - - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $em = $doctrine->getManager(); - $dinosaur = $form->getData(); - - $em->persist($dinosaur); - $em->flush(); - - $this->addFlash('success', 'The dinosaur has been created!'); - - return $this->redirectToRoute('app_list_dinosaurs'); - } - - return $this->render('create-dinosaur.html.twig', [ - 'form' => $form, - ]); - } - - #[Route( - '/dinosaurs/{id}/edit', - name: 'app_edit_dinosaur', - requirements: ['id' => '\d+'] - )] - public function edit(Request $request, int $id, ManagerRegistry $doctrine): Response - { - $dinosaur = $doctrine - ->getRepository(Dinosaur::class) - ->find($id); - - if (false === $dinosaur) { - throw $this->createNotFoundException('The dinosaur you are looking for does not exists.'); - } - - $form = $this->createForm(DinosaurType::class, $dinosaur); - - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $em = $doctrine->getManager(); - $dinosaur = $form->getData(); - - $em->flush(); - - $this->addFlash('success', 'The dinosaur has been edited!'); - - return $this->redirectToRoute('app_list_dinosaurs'); - } - - return $this->render('edit-dinosaur.html.twig', [ - 'form' => $form, - ]); - } - - #[Route( - '/dinosaurs/{id}/remove', - name: 'app_remove_dinosaur', - requirements: ['id' => '\d+'] - )] - public function remove(int $id, ManagerRegistry $doctrine): Response - { - $dinosaur = $doctrine - ->getRepository(Dinosaur::class) - ->find($id); - - if (false === $dinosaur) { - throw $this->createNotFoundException('The dinosaur you are looking for does not exists.'); - } - - $em = $doctrine->getManager(); - $em->remove($dinosaur); - $em->flush(); - - $this->addFlash('success', 'The dinosaur has been removed!'); - - return $this->redirectToRoute('app_list_dinosaurs'); - } -} diff --git a/src/Controller/SpeciesController.php b/src/Controller/SpeciesController.php deleted file mode 100644 index 7d356f8..0000000 --- a/src/Controller/SpeciesController.php +++ /dev/null @@ -1,109 +0,0 @@ -getRepository(Species::class) - ->findAll(); - - return $this->render('species-list.html.twig', [ - 'speciesList' => $speciesList, - ]); - } - - #[Route('/species/create', name: 'app_create_species')] - public function create(Request $request, ManagerRegistry $doctrine): Response - { - $form = $this->createForm(SpeciesType::class); - - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $em = $doctrine->getManager(); - $species = $form->getData(); - - $em->persist($species); - $em->flush(); - - $this->addFlash('success', 'The species has been created!'); - - return $this->redirectToRoute('app_list_species'); - } - - return $this->render('create-species.html.twig', [ - 'form' => $form, - ]); - } - - #[Route( - '/species/{id}/edit', - name: 'app_edit_species', - requirements: ['id' => '\d+'] - )] - public function edit(Request $request, int $id, ManagerRegistry $doctrine): Response - { - $species = $doctrine - ->getRepository(Species::class) - ->find($id); - - if (false === $species) { - throw $this->createNotFoundException('The species you are looking for does not exists.'); - } - - $form = $this->createForm(SpeciesType::class, $species); - - $form->handleRequest($request); - - if ($form->isSubmitted() && $form->isValid()) { - $em = $doctrine->getManager(); - $species = $form->getData(); - - $em->flush(); - - $this->addFlash('success', 'The species has been edited!'); - - return $this->redirectToRoute('app_list_species'); - } - - return $this->render('edit-species.html.twig', [ - 'form' => $form, - ]); - } - - #[Route( - '/species/{id}/remove', - name: 'app_remove_species', - requirements: ['id' => '\d+'] - )] - public function remove(int $id, ManagerRegistry $doctrine): Response - { - $species = $doctrine - ->getRepository(Species::class) - ->find($id); - - if (false === $species) { - throw $this->createNotFoundException('The species you are looking for does not exists.'); - } - - $em = $doctrine->getManager(); - $em->remove($species); - $em->flush(); - - $this->addFlash('success', 'The species has been removed!'); - - return $this->redirectToRoute('app_list_species'); - } -} diff --git a/src/DinosaursFinder.php b/src/DinosaursFinder.php deleted file mode 100644 index 5b0bed0..0000000 --- a/src/DinosaursFinder.php +++ /dev/null @@ -1,18 +0,0 @@ - $dinosaurs - */ - public function adultOnly(array $dinosaurs): array - { - return array_filter($dinosaurs, function (Dinosaur $dinosaur) { - return $dinosaur->getAge() >= 21; - }); - } -} diff --git a/src/Domain/Collection/DinosaursCollection.php b/src/Domain/Collection/DinosaursCollection.php new file mode 100644 index 0000000..da4a905 --- /dev/null +++ b/src/Domain/Collection/DinosaursCollection.php @@ -0,0 +1,23 @@ + + */ + public function search(?string $q): array; + + public function add(Dinosaur $dinosaur): void; + + public function remove(Dinosaur $dinosaur): void; +} diff --git a/src/Domain/Collection/SpeciesCollection.php b/src/Domain/Collection/SpeciesCollection.php new file mode 100644 index 0000000..d05f44a --- /dev/null +++ b/src/Domain/Collection/SpeciesCollection.php @@ -0,0 +1,24 @@ + + */ + public function findAll(); + + public function findByName(string $name): ?Species; + + public function add(Species $species): void; + + public function remove(Species $species): void; +} + diff --git a/src/Domain/Collection/UsersCollection.php b/src/Domain/Collection/UsersCollection.php new file mode 100644 index 0000000..eee4b47 --- /dev/null +++ b/src/Domain/Collection/UsersCollection.php @@ -0,0 +1,14 @@ +dinosaurId; + } +} diff --git a/src/Domain/Event/DinosaurIsBorn.php b/src/Domain/Event/DinosaurIsBorn.php new file mode 100644 index 0000000..70d304e --- /dev/null +++ b/src/Domain/Event/DinosaurIsBorn.php @@ -0,0 +1,18 @@ +dinosaurId; + } +} diff --git a/src/Domain/Event/EventInterface.php b/src/Domain/Event/EventInterface.php new file mode 100644 index 0000000..318d62e --- /dev/null +++ b/src/Domain/Event/EventInterface.php @@ -0,0 +1,10 @@ + */ + private array $events = []; + + public function register(EventInterface ...$events): void + { + array_push($this->events, ...$events); + } + + /** + * @return array + */ + public function getEvents(): array + { + return $this->events; + } + + public function flush(): void + { + $this->events = []; + } +} diff --git a/src/Domain/Exception/DinosaurAlreadyExistsException.php b/src/Domain/Exception/DinosaurAlreadyExistsException.php new file mode 100644 index 0000000..c4c0e02 --- /dev/null +++ b/src/Domain/Exception/DinosaurAlreadyExistsException.php @@ -0,0 +1,16 @@ +eyesColor = $eyesColor; } + + public function toArray(): array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'gender' => $this->gender, + 'species' => $this->species, + 'age' => $this->age, + 'eyesColor' => $this->eyesColor, + ]; + } } diff --git a/src/Entity/Species.php b/src/Domain/Model/Species.php similarity index 62% rename from src/Entity/Species.php rename to src/Domain/Model/Species.php index 61d5a90..2cd4748 100644 --- a/src/Entity/Species.php +++ b/src/Domain/Model/Species.php @@ -1,14 +1,11 @@ name = $name; $this->habitats = $habitats; $this->feeding = $feeding; - $this->dinosaurs = new ArrayCollection(); + $this->dinosaurs = []; } public function getId(): int @@ -56,18 +53,33 @@ public function setFeeding(string $feeding): void $this->feeding = $feeding; } - public function getDinosaurs(): Collection + public function getDinosaurs(): iterable { - return $this->dinosaurs; + yield from $this->dinosaurs; } public function addDinosaur(Dinosaur $dinosaur): void { - $this->dinosaurs->add($dinosaur); + $this->dinosaurs[] = $dinosaur; } public function removeDinosaur(Dinosaur $dinosaur): void { - $this->dinosaurs->removeElement($dinosaur); + $this->dinosaurs = array_filter( + [...$this->dinosaurs], + function (Dinosaur $d) use ($dinosaur) { + return $d->getId() !== $dinosaur->getId(); + } + ); + } + + public function toArray(): array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'habitats' => $this->habitats, + 'feeding' => $this->feeding, + ]; } } diff --git a/src/Entity/User.php b/src/Domain/Model/User.php similarity index 68% rename from src/Entity/User.php rename to src/Domain/Model/User.php index c976892..837d095 100644 --- a/src/Entity/User.php +++ b/src/Domain/Model/User.php @@ -2,15 +2,13 @@ declare(strict_types=1); -namespace App\Entity; +namespace Domain\Model; -use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; -use Symfony\Component\Security\Core\User\UserInterface; - -class User implements UserInterface, PasswordAuthenticatedUserInterface +class User { private int $id; private ?string $password; + private ?string $plainPassword = null; public function __construct( private string $email, @@ -23,17 +21,19 @@ public function getId(): int return $this->id; } - public function getUserIdentifier(): string + public function getEmail(): string { return $this->email; } - public function getRoles(): array + public function setPlainPassword(string $plainPassword): void { - $roles = $this->roles; - $roles[] = 'ROLE_USER'; + $this->plainPassword = $plainPassword; + } - return array_unique($roles); + public function getPlainPassword(): ?string + { + return $this->plainPassword; } public function setHashedPassword(string $hashedPassword): void @@ -46,7 +46,11 @@ public function getPassword(): ?string return $this->password; } - public function eraseCredentials(): void + public function getRoles(): array { + $roles = $this->roles; + $roles[] = 'ROLE_USER'; + + return array_unique($roles); } } diff --git a/src/Domain/Query/GetAllDinosaurs/Handler.php b/src/Domain/Query/GetAllDinosaurs/Handler.php new file mode 100644 index 0000000..9b897a4 --- /dev/null +++ b/src/Domain/Query/GetAllDinosaurs/Handler.php @@ -0,0 +1,27 @@ +dinosaursCollection->search($query->search); + + return array_map( + fn (ModelDinosaur $dinosaur) => new Dinosaur($dinosaur), + $dinosaurs + ); + } +} diff --git a/src/Domain/Query/GetAllDinosaurs/Query.php b/src/Domain/Query/GetAllDinosaurs/Query.php new file mode 100644 index 0000000..215bb66 --- /dev/null +++ b/src/Domain/Query/GetAllDinosaurs/Query.php @@ -0,0 +1,13 @@ +speciesCollection->findAll(); + + return array_map( + fn (ModelSpecies $species) => new Species($species), + $species + ); + } +} diff --git a/src/Domain/Query/GetAllSpecies/Query.php b/src/Domain/Query/GetAllSpecies/Query.php new file mode 100644 index 0000000..54a4a7c --- /dev/null +++ b/src/Domain/Query/GetAllSpecies/Query.php @@ -0,0 +1,12 @@ +dinosaursCollection->find($query->id); + + if ($dinosaur === null) { + throw new DinosaurNotFoundException($query->id); + } + + return new Dinosaur($dinosaur); + } +} diff --git a/src/Domain/Query/GetSingleDinosaur/Query.php b/src/Domain/Query/GetSingleDinosaur/Query.php new file mode 100644 index 0000000..9456f39 --- /dev/null +++ b/src/Domain/Query/GetSingleDinosaur/Query.php @@ -0,0 +1,13 @@ +speciesCollection->find($query->id); + + if ($speciesModel === null) { + throw new SpeciesNotFoundException($query->id); + } + + return new Species($speciesModel); + } +} diff --git a/src/Domain/Query/GetSingleSpecies/Query.php b/src/Domain/Query/GetSingleSpecies/Query.php new file mode 100644 index 0000000..2073385 --- /dev/null +++ b/src/Domain/Query/GetSingleSpecies/Query.php @@ -0,0 +1,13 @@ +id = $dinosaurModel->getId(); + $this->name = $dinosaurModel->getName(); + $this->gender = $dinosaurModel->getGender(); + $this->species = new Species($dinosaurModel->getSpecies()); + $this->age = $dinosaurModel->getAge(); + $this->eyesColor = $dinosaurModel->getEyesColor(); + } + + public function getId(): int + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getGender(): string + { + return $this->gender; + } + + public function setGender(string $gender): void + { + $this->gender = $gender; + } + + public function getSpecies(): Species + { + return $this->species; + } + + public function setSpecies(Species $species): void + { + $this->species = $species; + } + + public function getAge(): int + { + return $this->age; + } + + public function setAge(int $age): void + { + $this->age = $age; + } + + public function getEyesColor(): string + { + return $this->eyesColor; + } + + public function setEyesColor(string $eyesColor): void + { + $this->eyesColor = $eyesColor; + } +} diff --git a/src/Domain/ReadModel/Species.php b/src/Domain/ReadModel/Species.php new file mode 100644 index 0000000..8472071 --- /dev/null +++ b/src/Domain/ReadModel/Species.php @@ -0,0 +1,59 @@ +id = $modelSpecies->getId(); + $this->name = $modelSpecies->getName(); + $this->habitats = $modelSpecies->getHabitats(); + $this->feeding = $modelSpecies->getFeeding(); + } + + public function getId(): int + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function setName(string $name): void + { + $this->name = $name; + } + + public function getHabitats(): array + { + return $this->habitats; + } + + public function setHabitats(array $habitats): void + { + $this->habitats = $habitats; + } + + public function getFeeding(): string + { + return $this->feeding; + } + + public function setFeeding(string $feeding): void + { + $this->feeding = $feeding; + } +} diff --git a/src/Domain/UseCase/CreateDinosaur/Handler.php b/src/Domain/UseCase/CreateDinosaur/Handler.php new file mode 100644 index 0000000..913f4e8 --- /dev/null +++ b/src/Domain/UseCase/CreateDinosaur/Handler.php @@ -0,0 +1,56 @@ +dinosaursCollection + ->findByName($input->name); + + if (null !== $existingDinosaurs) { + throw new DinosaurAlreadyExistsException($input->name); + } + + $species = $this + ->speciesCollection + ->find($input->speciesId); + + if (null === $species) { + throw new SpeciesNotFoundException($input->speciesId); + } + + $dinosaur = new Dinosaur( + $input->name, + $input->gender, + $species, + $input->age, + $input->eyesColor + ); + + $this->dinosaursCollection->add($dinosaur); + + $this->eventsRegisterer->register(new DinosaurIsBorn($dinosaur->getId())); + + return new Output($dinosaur); + } +} diff --git a/src/Domain/UseCase/CreateDinosaur/Input.php b/src/Domain/UseCase/CreateDinosaur/Input.php new file mode 100644 index 0000000..7de1e8c --- /dev/null +++ b/src/Domain/UseCase/CreateDinosaur/Input.php @@ -0,0 +1,17 @@ +speciesCollection->findByName($input->name)) { + throw new SpeciesAlreadyExistsException($input->name); + } + + $species = new Species( + $input->name, + $input->habitats, + $input->feeding, + ); + + $this->speciesCollection->add($species); + + return new Output($species); + } +} diff --git a/src/Domain/UseCase/CreateSpecies/Input.php b/src/Domain/UseCase/CreateSpecies/Input.php new file mode 100644 index 0000000..f24a7e0 --- /dev/null +++ b/src/Domain/UseCase/CreateSpecies/Input.php @@ -0,0 +1,15 @@ +dinosaursCollection + ->find($input->id); + + if (null === $dinosaur) { + throw new DinosaurAlreadyExistsException($input->name); + } + + $species = $this + ->speciesCollection + ->find($input->speciesId); + + if (null === $species) { + throw new SpeciesNotFoundException($input->speciesId); + } + + $dinosaur->setName($input->name); + $dinosaur->setGender($input->gender); + $dinosaur->setSpecies($species); + $dinosaur->setAge($input->age); + $dinosaur->setEyesColor($input->eyesColor); + + return new Output($dinosaur); + } +} diff --git a/src/Domain/UseCase/EditDinosaur/Input.php b/src/Domain/UseCase/EditDinosaur/Input.php new file mode 100644 index 0000000..61ee172 --- /dev/null +++ b/src/Domain/UseCase/EditDinosaur/Input.php @@ -0,0 +1,32 @@ +getId(), + $dinosaur->getName(), + $dinosaur->getGender(), + (string) $dinosaur->getSpecies()->getId(), + $dinosaur->getAge(), + $dinosaur->getEyesColor() + ); + } +} diff --git a/src/Domain/UseCase/EditDinosaur/Output.php b/src/Domain/UseCase/EditDinosaur/Output.php new file mode 100644 index 0000000..329bcf6 --- /dev/null +++ b/src/Domain/UseCase/EditDinosaur/Output.php @@ -0,0 +1,15 @@ +speciesCollection->find($input->speciesId); + + if (null === $species) { + throw new SpeciesNotFoundException($input->speciesId); + } + + $species->setName($input->name); + $species->setHabitats($input->habitats); + $species->setFeeding($input->feeding); + + $this->speciesCollection->add($species); + + return new Output($species); + } +} diff --git a/src/Domain/UseCase/EditSpecies/Input.php b/src/Domain/UseCase/EditSpecies/Input.php new file mode 100644 index 0000000..f2e5a5d --- /dev/null +++ b/src/Domain/UseCase/EditSpecies/Input.php @@ -0,0 +1,28 @@ +getId(), + name: $species->getName(), + habitats: $species->getHabitats(), + feeding: $species->getFeeding() + ); + } +} diff --git a/src/Domain/UseCase/EditSpecies/Output.php b/src/Domain/UseCase/EditSpecies/Output.php new file mode 100644 index 0000000..58e6102 --- /dev/null +++ b/src/Domain/UseCase/EditSpecies/Output.php @@ -0,0 +1,15 @@ +usersCollection->findOneByEmail($input->email); + + if (null !== $existingUser) { + throw new UserAlreadyExistsException($input->email); + } + + $user = new User( + email: $input->email, + ); + + $user->setPlainPassword($input->password); + + $this->usersCollection->add($user); + + return new Output(user: $user); + } +} diff --git a/src/Domain/UseCase/RegisterUser/Input.php b/src/Domain/UseCase/RegisterUser/Input.php new file mode 100644 index 0000000..8582252 --- /dev/null +++ b/src/Domain/UseCase/RegisterUser/Input.php @@ -0,0 +1,14 @@ +dinosaursCollection + ->find($input->id); + + if (null === $dinosaur) { + throw new DinosaurNotFoundException($input->id); + } + + $this->dinosaursCollection->remove($dinosaur); + + $this->eventsRegisterer->register(new DinosaurDied( + $dinosaur->getId(), + $dinosaur->getName() + )); + + return new Output(); + } +} diff --git a/src/Domain/UseCase/RemoveDinosaur/Input.php b/src/Domain/UseCase/RemoveDinosaur/Input.php new file mode 100644 index 0000000..ad21392 --- /dev/null +++ b/src/Domain/UseCase/RemoveDinosaur/Input.php @@ -0,0 +1,13 @@ +speciesCollection->find($input->id); + + if (null === $species) { + throw new SpeciesNotFoundException($input->id); + } + + $this->speciesCollection->remove($species); + + return new Output(); + } +} diff --git a/src/Domain/UseCase/RemoveSpecies/Input.php b/src/Domain/UseCase/RemoveSpecies/Input.php new file mode 100644 index 0000000..5503757 --- /dev/null +++ b/src/Domain/UseCase/RemoveSpecies/Input.php @@ -0,0 +1,13 @@ +add('email', EmailType::class) - ->add('password', PasswordType::class) - ->add('submit', SubmitType::class, [ - 'label' => 'Register', - ]) - ->setDataMapper($this); - } - - public function configureOptions(OptionsResolver $resolver): void - { - $resolver->setDefaults([ - 'data_class' => User::class, - 'empty_data' => function (FormInterface $form) { - return new User( - $form->get('email')->getData(), - ); - }, - ]); - } - - public function mapDataToForms(mixed $viewData, \Traversable $forms): void - { - if (null === $viewData) { - return; - } - } - - public function mapFormsToData(\Traversable $forms, mixed &$viewData): void - { - $forms = iterator_to_array($forms); - - $viewData = new User( - $forms['email']->getData(), - ); - - $hashedPassword = $this->passwordHasher->hashPassword($viewData, $forms['password']->getData()); - - $viewData->setHashedPassword($hashedPassword); - } -} diff --git a/src/DataFixtures/AppFixtures.php b/src/Infrastructure/Doctrine/DataFixtures/AppFixtures.php similarity index 90% rename from src/DataFixtures/AppFixtures.php rename to src/Infrastructure/Doctrine/DataFixtures/AppFixtures.php index fc71111..523be5b 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/Infrastructure/Doctrine/DataFixtures/AppFixtures.php @@ -1,10 +1,11 @@ passwordHasher->hashPassword($admin, 'admin'); + $hashedPassword = $this->passwordHasher->hashPassword(new User($admin), 'admin'); $admin->setHashedPassword($hashedPassword); $manager->persist($admin); @@ -35,11 +36,11 @@ public function load(ObjectManager $manager): void * Create basic users with the default role ROLE_USER */ for ($i = 0; $i < 10; ++$i) { - $user = new User( + $user = new ModelUser( 'user_' . $i . '@mail.com' ); - $hashedPassword = $this->passwordHasher->hashPassword($user, 'password'); + $hashedPassword = $this->passwordHasher->hashPassword(new User($user), 'password'); $user->setHashedPassword($hashedPassword); $manager->persist($user); diff --git a/src/Infrastructure/Doctrine/EventListener/HashUserPasswordListener.php b/src/Infrastructure/Doctrine/EventListener/HashUserPasswordListener.php new file mode 100644 index 0000000..3af4cff --- /dev/null +++ b/src/Infrastructure/Doctrine/EventListener/HashUserPasswordListener.php @@ -0,0 +1,39 @@ +getObject(); + + if (!$entity instanceof User) { + return; + } + + $plainPassword = $entity->getPlainPassword(); + + if (null === $plainPassword) { + return; + } + + $securityUser = new SecurityUser($entity); + + $hashedPassword = $this->passwordHasher->hashPassword($securityUser, $plainPassword); + + $entity->setHashedPassword($hashedPassword); + } +} diff --git a/src/Infrastructure/Doctrine/Repository/DinosaurRepository.php b/src/Infrastructure/Doctrine/Repository/DinosaurRepository.php new file mode 100644 index 0000000..e897fb6 --- /dev/null +++ b/src/Infrastructure/Doctrine/Repository/DinosaurRepository.php @@ -0,0 +1,56 @@ +objectManager = $registry->getManager(); + } + + public function findByName(string $name): ?Dinosaur + { + return $this->createQueryBuilder('d') + ->where('d.name = :name') + ->setParameter('name', $name) + ->getQuery() + ->getOneOrNullResult(); + } + + public function search(?string $q): array + { + if (null === $q) { + return $this->findAll(); + } + + return $this->createQueryBuilder('d') + ->where('d.name = :q') + ->setParameter('q', $q) + ->getQuery() + ->getResult(); + } + + public function add(Dinosaur $dinosaur): void + { + $this->objectManager->persist($dinosaur); + $this->objectManager->flush(); + } + + public function remove(Dinosaur $dinosaur): void + { + $this->objectManager->remove($dinosaur); + $this->objectManager->flush(); + } +} diff --git a/src/Infrastructure/Doctrine/Repository/SpeciesRepository.php b/src/Infrastructure/Doctrine/Repository/SpeciesRepository.php new file mode 100644 index 0000000..77e58e9 --- /dev/null +++ b/src/Infrastructure/Doctrine/Repository/SpeciesRepository.php @@ -0,0 +1,42 @@ +objectManager = $registry->getManager(); + } + + public function findByName(string $name): ?Species + { + return $this->createQueryBuilder('s') + ->where('s.name = :name') + ->setParameter('name', $name) + ->getQuery() + ->getOneOrNullResult() + ; + } + + public function add(Species $species): void + { + $this->objectManager->persist($species); + } + + public function remove(Species $species): void + { + $this->objectManager->remove($species); + } +} diff --git a/src/Infrastructure/Doctrine/Repository/UserRepository.php b/src/Infrastructure/Doctrine/Repository/UserRepository.php new file mode 100644 index 0000000..8c00952 --- /dev/null +++ b/src/Infrastructure/Doctrine/Repository/UserRepository.php @@ -0,0 +1,37 @@ +objectManager = $registry->getManager(); + } + + public function findOneByEmail(string $email): ?User + { + return $this->createQueryBuilder('u') + ->where('u.email = :email') + ->setParameter('email', $email) + ->getQuery() + ->getOneOrNullResult(); + } + + public function add(User $user): void + { + $this->objectManager->persist($user); + $this->objectManager->flush(); + } +} diff --git a/src/Infrastructure/Symfony/Messenger/CommandBus.php b/src/Infrastructure/Symfony/Messenger/CommandBus.php new file mode 100644 index 0000000..1eaebed --- /dev/null +++ b/src/Infrastructure/Symfony/Messenger/CommandBus.php @@ -0,0 +1,34 @@ +handle($input); + } catch (HandlerFailedException $handlerFailedException) { + $nestedExceptions = $handlerFailedException->getWrappedExceptions(); + + if (false === $nested = current($nestedExceptions)) { + throw $handlerFailedException; + } + + throw $nested; + } + } +} diff --git a/src/Infrastructure/Symfony/Messenger/EventBus.php b/src/Infrastructure/Symfony/Messenger/EventBus.php new file mode 100644 index 0000000..ce47601 --- /dev/null +++ b/src/Infrastructure/Symfony/Messenger/EventBus.php @@ -0,0 +1,34 @@ +handle($event); + } catch (HandlerFailedException $handlerFailedException) { + $nestedExceptions = $handlerFailedException->getWrappedExceptions(); + + if (false === $nested = current($nestedExceptions)) { + throw $handlerFailedException; + } + + throw $nested; + } + } +} diff --git a/src/Infrastructure/Symfony/Messenger/Middleware/DomainEventDispatcher.php b/src/Infrastructure/Symfony/Messenger/Middleware/DomainEventDispatcher.php new file mode 100644 index 0000000..9c90087 --- /dev/null +++ b/src/Infrastructure/Symfony/Messenger/Middleware/DomainEventDispatcher.php @@ -0,0 +1,51 @@ +next()->handle($envelope, $stack); + + $stamp = $envelope->last(HandledStamp::class); + + if (!$stamp instanceof HandledStamp) { + return $envelope; + } + + /* + * This entity manager clear operation is mandatory since we need to have + * the freshest object as possible as we always read entities after several + * changes that might not have been updated by doctrine. + */ + $this->em->clear(); + + $events = $this->eventsRegisterer->getEvents(); + + foreach ($events as $event) { + $this->eventBus->dispatch($event); + } + + $this->eventsRegisterer->flush(); + + return $envelope; + } +} diff --git a/src/Infrastructure/Symfony/Messenger/QueryBus.php b/src/Infrastructure/Symfony/Messenger/QueryBus.php new file mode 100644 index 0000000..2f81666 --- /dev/null +++ b/src/Infrastructure/Symfony/Messenger/QueryBus.php @@ -0,0 +1,34 @@ +handle($input); + } catch (HandlerFailedException $handlerFailedException) { + $nestedExceptions = $handlerFailedException->getWrappedExceptions(); + + if (false === $nested = current($nestedExceptions)) { + throw $handlerFailedException; + } + + throw $nested; + } + } +} diff --git a/src/Kernel.php b/src/Kernel.php index 779cd1f..7819c06 100644 --- a/src/Kernel.php +++ b/src/Kernel.php @@ -1,11 +1,30 @@ getProjectDir()}/config"; + $container->addResource(new FileResource("{$confDir}/bundles.php")); + + $loader->load("{$confDir}/{packages}/*".self::CONFIG_EXTS, 'glob'); + $loader->load("{$confDir}/{packages}/{$this->environment}/**/*".self::CONFIG_EXTS, 'glob'); + + $loader->load("{$confDir}/{services}".self::CONFIG_EXTS, 'glob'); + $loader->load("{$confDir}/{services}/**/*".self::CONFIG_EXTS, 'glob'); + } } diff --git a/src/Repository/.gitignore b/src/Repository/.gitignore deleted file mode 100644 index e69de29..0000000 diff --git a/src/Repository/DinosaurRepository.php b/src/Repository/DinosaurRepository.php deleted file mode 100644 index 1016b70..0000000 --- a/src/Repository/DinosaurRepository.php +++ /dev/null @@ -1,28 +0,0 @@ -findAll(); - } - - return $this->createQueryBuilder('d') - ->where('d.name = :q') - ->setParameter('q', $q) - ->getQuery() - ->getResult(); - } -} diff --git a/src/Repository/SpeciesRepository.php b/src/Repository/SpeciesRepository.php deleted file mode 100644 index 76d592c..0000000 --- a/src/Repository/SpeciesRepository.php +++ /dev/null @@ -1,15 +0,0 @@ -