diff --git a/.env.dist b/.env.dist index eeafa62..28137cc 100644 --- a/.env.dist +++ b/.env.dist @@ -7,3 +7,16 @@ MYSQL_VERSION=8.0.27 MYSQL_DATABASE=databasorus MYSQL_USER=user MYSQL_PASSWORD=password + +###> symfony/messenger ### +# Choose one of the transports below +# MESSENGER_TRANSPORT_DSN=doctrine://default +# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages +# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages +###< symfony/messenger ### + +###> symfony/lock ### +# Choose one of the stores below +# postgresql+advisory://db_user:db_password@localhost/db_name +LOCK_DSN=flock +###< symfony/lock ### diff --git a/Makefile b/Makefile index 0ef82db..d12b2af 100644 --- a/Makefile +++ b/Makefile @@ -32,3 +32,8 @@ fixtures-load: .PHONY: reset-db reset-db: database-drop database-create database-migrate fixtures-load + docker compose run --rm php bin/console doctrine:fixtures:load + +.PHONY: worker +worker: + docker compose run --rm php bin/console messenger:consume async -vv diff --git a/composer.json b/composer.json index f760f5c..8a99cf2 100644 --- a/composer.json +++ b/composer.json @@ -11,9 +11,11 @@ "doctrine/doctrine-bundle": "^2.12", "doctrine/doctrine-migrations-bundle": "^3.3", "doctrine/orm": "^3.1", + "elasticsearch/elasticsearch": "^8.6", "phpdocumentor/reflection-docblock": "^5.4", "symfony/asset": "^7.0", "symfony/console": "^7.0", + "symfony/doctrine-messenger": "^7.0", "symfony/dotenv": "^7.0", "symfony/expression-language": "^7.0", "symfony/flex": "^2.4.5", @@ -21,7 +23,9 @@ "symfony/framework-bundle": "^7.0", "symfony/http-client": "^7.0", "symfony/intl": "^7.0", + "symfony/lock": "^7.0", "symfony/mailer": "^7.0", + "symfony/messenger": "^7.0", "symfony/mime": "^7.0", "symfony/monolog-bundle": "^3.10", "symfony/notifier": "^7.0", @@ -54,7 +58,8 @@ }, "config": { "allow-plugins": { - "symfony/*": true + "symfony/*": true, + "php-http/discovery": true }, "optimize-autoloader": true, "preferred-install": { diff --git a/composer.lock b/composer.lock index a3c72ad..2c574d8 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": "a5b6857e351b48ef5e0f02910f02413b", "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", @@ -1360,6 +1360,119 @@ ], "time": "2023-10-06T06:47:41+00:00" }, + { + "name": "elastic/transport", + "version": "v8.8.0", + "source": { + "type": "git", + "url": "https://github.com/elastic/elastic-transport-php.git", + "reference": "cdf9f63a16ec6bfb4c881ab89aa0e2a61fb7c20b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/elastic/elastic-transport-php/zipball/cdf9f63a16ec6bfb4c881ab89aa0e2a61fb7c20b", + "reference": "cdf9f63a16ec6bfb4c881ab89aa0e2a61fb7c20b", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.0", + "php": "^7.4 || ^8.0", + "php-http/discovery": "^1.14", + "php-http/httplug": "^2.3", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0 || ^2.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "nyholm/psr7": "^1.5", + "php-http/mock-client": "^1.5", + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Elastic\\Transport\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "HTTP transport PHP library for Elastic products", + "keywords": [ + "PSR_17", + "elastic", + "http", + "psr-18", + "psr-7", + "transport" + ], + "support": { + "issues": "https://github.com/elastic/elastic-transport-php/issues", + "source": "https://github.com/elastic/elastic-transport-php/tree/v8.8.0" + }, + "time": "2023-11-08T10:51:51+00:00" + }, + { + "name": "elasticsearch/elasticsearch", + "version": "v8.13.0", + "source": { + "type": "git", + "url": "https://github.com/elastic/elasticsearch-php.git", + "reference": "221723e9497515ec82833995a97c8546d9b6499a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/elastic/elasticsearch-php/zipball/221723e9497515ec82833995a97c8546d9b6499a", + "reference": "221723e9497515ec82833995a97c8546d9b6499a", + "shasum": "" + }, + "require": { + "elastic/transport": "^8.8", + "guzzlehttp/guzzle": "^7.0", + "php": "^7.4 || ^8.0", + "psr/http-client": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "psr/log": "^1|^2|^3" + }, + "require-dev": { + "ext-yaml": "*", + "ext-zip": "*", + "mockery/mockery": "^1.5", + "nyholm/psr7": "^1.5", + "php-http/message-factory": "^1.0", + "php-http/mock-client": "^1.5", + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9.5", + "psr/http-factory": "^1.0", + "symfony/finder": "~4.0", + "symfony/http-client": "^5.0|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Elastic\\Elasticsearch\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHP Client for Elasticsearch", + "keywords": [ + "client", + "elastic", + "elasticsearch", + "search" + ], + "support": { + "issues": "https://github.com/elastic/elasticsearch-php/issues", + "source": "https://github.com/elastic/elasticsearch-php/tree/v8.13.0" + }, + "time": "2024-03-27T15:09:06+00:00" + }, { "name": "friendsofphp/proxy-manager-lts", "version": "v1.0.18", @@ -1442,6 +1555,331 @@ ], "time": "2024-03-20T12:50:41+00:00" }, + { + "name": "guzzlehttp/guzzle", + "version": "7.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/41042bc7ab002487b876a0683fc8dce04ddce104", + "reference": "41042bc7ab002487b876a0683fc8dce04ddce104", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "ext-curl": "*", + "php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.8.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:35:24+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/bbff78d96034045e58e13dedd6ad91b5d1253223", + "reference": "bbff78d96034045e58e13dedd6ad91b5d1253223", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.0.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:19:20+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "2.6.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/45b30f99ac27b5ca93cb4831afe16285f57b8221", + "reference": "45b30f99ac27b5ca93cb4831afe16285f57b8221", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "^0.9", + "phpunit/phpunit": "^8.5.36 || ^9.6.15" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "bamarni-bin": { + "bin-links": true, + "forward-command": false + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.6.2" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2023-12-03T20:05:35+00:00" + }, { "name": "laminas/laminas-code", "version": "4.13.0", @@ -1606,6 +2044,194 @@ ], "time": "2024-04-12T21:02:21+00:00" }, + { + "name": "php-http/discovery", + "version": "1.19.4", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "0700efda8d7526335132360167315fdab3aeb599" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/0700efda8d7526335132360167315fdab3aeb599", + "reference": "0700efda8d7526335132360167315fdab3aeb599", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0|^2.0", + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0", + "zendframework/zend-diactoros": "*" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "*", + "psr/http-factory-implementation": "*", + "psr/http-message-implementation": "*" + }, + "require-dev": { + "composer/composer": "^1.0.2|^2.0", + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1 || ^7.3", + "sebastian/comparator": "^3.0.5 || ^4.0.8", + "symfony/phpunit-bridge": "^6.4.4 || ^7.0.1" + }, + "type": "composer-plugin", + "extra": { + "class": "Http\\Discovery\\Composer\\Plugin", + "plugin-optional": true + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + }, + "exclude-from-classmap": [ + "src/Composer/Plugin.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr17", + "psr7" + ], + "support": { + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.19.4" + }, + "time": "2024-03-29T13:00:05+00:00" + }, + { + "name": "php-http/httplug", + "version": "2.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/httplug.git", + "reference": "625ad742c360c8ac580fcc647a1541d29e257f67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/httplug/zipball/625ad742c360c8ac580fcc647a1541d29e257f67", + "reference": "625ad742c360c8ac580fcc647a1541d29e257f67", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "php-http/promise": "^1.1", + "psr/http-client": "^1.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage": "^4.1 || ^5.0 || ^6.0", + "phpspec/phpspec": "^5.1 || ^6.0 || ^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "support": { + "issues": "https://github.com/php-http/httplug/issues", + "source": "https://github.com/php-http/httplug/tree/2.4.0" + }, + "time": "2023-04-14T15:10:03+00:00" + }, + { + "name": "php-http/promise", + "version": "1.3.1", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/fc85b1fba37c169a69a07ef0d5a8075770cc1f83", + "reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage": "^4.3.2 || ^6.3", + "phpspec/phpspec": "^5.1.2 || ^6.2 || ^7.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/php-http/promise/issues", + "source": "https://github.com/php-http/promise/tree/1.3.1" + }, + "time": "2024-03-15T13:55:21+00:00" + }, { "name": "phpdocumentor/reflection-common", "version": "2.2.0", @@ -1973,37 +2599,194 @@ "psr" ], "support": { - "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/2.0.2" + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "e616d01114759c4c489f93b099585439f795fe35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35", + "reference": "e616d01114759c4c489f93b099585439f795fe35", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/1.0.2" }, - "time": "2021-11-05T16:47:00+00:00" + "time": "2023-04-10T20:10:41+00:00" }, { - "name": "psr/event-dispatcher", - "version": "1.0.0", + "name": "psr/http-message", + "version": "2.0", "source": { "type": "git", - "url": "https://github.com/php-fig/event-dispatcher.git", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", - "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "php": ">=7.2.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\EventDispatcher\\": "src/" + "Psr\\Http\\Message\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -2013,20 +2796,23 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], - "description": "Standard interfaces for event handling.", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "events", + "http", + "http-message", "psr", - "psr-14" + "psr-7", + "request", + "response" ], "support": { - "issues": "https://github.com/php-fig/event-dispatcher/issues", - "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2019-01-08T18:20:26+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/link", @@ -2134,6 +2920,50 @@ }, "time": "2021-07-14T16:46:02+00:00" }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, { "name": "symfony/asset", "version": "v7.0.3", @@ -2870,6 +3700,78 @@ ], "time": "2024-03-19T09:29:21+00:00" }, + { + "name": "symfony/doctrine-messenger", + "version": "v7.0.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/doctrine-messenger.git", + "reference": "227cbb2cda296d724a8e08376ad6db73a0335538" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/doctrine-messenger/zipball/227cbb2cda296d724a8e08376ad6db73a0335538", + "reference": "227cbb2cda296d724a8e08376ad6db73a0335538", + "shasum": "" + }, + "require": { + "doctrine/dbal": "^3.6|^4", + "php": ">=8.2", + "symfony/messenger": "^6.4|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "doctrine/persistence": "<1.3" + }, + "require-dev": { + "doctrine/persistence": "^1.3|^2|^3", + "symfony/property-access": "^6.4|^7.0", + "symfony/serializer": "^6.4|^7.0" + }, + "type": "symfony-messenger-bridge", + "autoload": { + "psr-4": { + "Symfony\\Component\\Messenger\\Bridge\\Doctrine\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Doctrine Messenger Bridge", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/doctrine-messenger/tree/v7.0.6" + }, + "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-03-19T09:26:35+00:00" + }, { "name": "symfony/dotenv", "version": "v7.0.4", @@ -4113,6 +5015,84 @@ ], "time": "2024-01-23T15:02:46+00:00" }, + { + "name": "symfony/lock", + "version": "v7.0.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/lock.git", + "reference": "c1fc92e5ba2a4d397751ac0df06689a187059402" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/lock/zipball/c1fc92e5ba2a4d397751ac0df06689a187059402", + "reference": "c1fc92e5ba2a4d397751ac0df06689a187059402", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3" + }, + "conflict": { + "doctrine/dbal": "<3.6", + "symfony/cache": "<6.4" + }, + "require-dev": { + "doctrine/dbal": "^3.6|^4", + "predis/predis": "^1.1|^2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Lock\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jérémy Derussé", + "email": "jeremy@derusse.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Creates and manages locks, a mechanism to provide exclusive access to a shared resource", + "homepage": "https://symfony.com", + "keywords": [ + "cas", + "flock", + "locking", + "mutex", + "redlock", + "semaphore" + ], + "support": { + "source": "https://github.com/symfony/lock/tree/v7.0.6" + }, + "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-03-19T09:26:35+00:00" + }, { "name": "symfony/mailer", "version": "v7.0.6", @@ -4193,6 +5173,92 @@ ], "time": "2024-03-28T09:20:36+00:00" }, + { + "name": "symfony/messenger", + "version": "v7.0.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/messenger.git", + "reference": "4e281ef8bf5397be36fe14d64eb665fa12a945ad" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/messenger/zipball/4e281ef8bf5397be36fe14d64eb665fa12a945ad", + "reference": "4e281ef8bf5397be36fe14d64eb665fa12a945ad", + "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.6" + }, + "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-03-19T11:57:22+00:00" + }, { "name": "symfony/mime", "version": "v7.0.6", @@ -7112,34 +8178,34 @@ }, { "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 +8236,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 +8248,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 +8315,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 +8327,7 @@ "type": "tidelift" } ], - "time": "2023-11-21T18:54:41+00:00" + "time": "2024-04-18T11:59:33+00:00" }, { "name": "webmozart/assert", diff --git a/config/doctrine/orm/Dinosaur.orm.xml b/config/doctrine/orm/Dinosaur.orm.xml index 2dd902f..e1f769d 100644 --- a/config/doctrine/orm/Dinosaur.orm.xml +++ b/config/doctrine/orm/Dinosaur.orm.xml @@ -24,6 +24,11 @@ target-entity="App\Entity\Species" inversed-by="dinosaurs" /> + + diff --git a/config/doctrine/orm/Park.orm.xml b/config/doctrine/orm/Park.orm.xml new file mode 100644 index 0000000..390f843 --- /dev/null +++ b/config/doctrine/orm/Park.orm.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + diff --git a/config/packages/http_discovery.yaml b/config/packages/http_discovery.yaml new file mode 100644 index 0000000..2a789e7 --- /dev/null +++ b/config/packages/http_discovery.yaml @@ -0,0 +1,10 @@ +services: + Psr\Http\Message\RequestFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\ResponseFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\ServerRequestFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\StreamFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\UploadedFileFactoryInterface: '@http_discovery.psr17_factory' + Psr\Http\Message\UriFactoryInterface: '@http_discovery.psr17_factory' + + http_discovery.psr17_factory: + class: Http\Discovery\Psr17Factory diff --git a/config/packages/lock.yaml b/config/packages/lock.yaml new file mode 100644 index 0000000..574879f --- /dev/null +++ b/config/packages/lock.yaml @@ -0,0 +1,2 @@ +framework: + lock: '%env(LOCK_DSN)%' diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml new file mode 100644 index 0000000..697a115 --- /dev/null +++ b/config/packages/messenger.yaml @@ -0,0 +1,31 @@ +framework: + messenger: + default_bus: command_bus + buses: + command_bus: + middleware: + - doctrine_transaction + - dispatch_after_current_bus + - App\Middleware\LockMiddleware + event_bus: + default_middleware: allow_no_handlers + middleware: + - doctrine_transaction + failure_transport: failed + transports: + async_high_priority: + dsn: '%env(MESSENGER_TRANSPORT_DSN)%' + options: + queue_name: high_priority + async_low_priority: + dsn: '%env(MESSENGER_TRANSPORT_DSN)%' + options: + queue_name: low_priority + failed: + dsn: '%env(MESSENGER_TRANSPORT_DSN)%' + options: + queue_name: failed + routing: + 'App\Message\Food\Consume': async_low_priority + 'App\Message\Food\Refill': async_high_priority + 'App\Event\AsyncLowPriorityEvent': async_low_priority diff --git a/config/services.yaml b/config/services.yaml index 1d3246d..9a20d90 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -24,5 +24,16 @@ services: - '../src/Entity/' - '../src/Kernel.php' + App\Bus\CommandBus: + $messageBus: '@command_bus' + + Elastic\Elasticsearch\Client: + class: Elastic\Elasticsearch\Client + factory: ['Elastic\Elasticsearch\ClientBuilder', 'fromConfig'] + arguments: + - + hosts: + - 'elasticsearch:9200' + # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones diff --git a/docker-compose.yml b/docker-compose.yml index 6f9f8ba..1b86bb5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,5 +42,16 @@ services: - db-data:/var/lib/mysql:rw restart: unless-stopped + elasticsearch: + image: docker.elastic.co/elasticsearch/elasticsearch:7.16.3 + volumes: + - 'elasticsearch:/usr/share/elasticsearch/data' + ports: + - 9200:9200 + environment: + - discovery.type=single-node + - "ES_JAVA_OPTS=-Xms512m -Xmx512m" + volumes: db-data: ~ + elasticsearch: ~ diff --git a/migrations/Version20230208124132.php b/migrations/Version20230208124132.php new file mode 100644 index 0000000..7e3d23f --- /dev/null +++ b/migrations/Version20230208124132.php @@ -0,0 +1,29 @@ +addSql('CREATE TABLE park (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, food_amount INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE messenger_messages (id BIGINT AUTO_INCREMENT NOT NULL, body LONGTEXT NOT NULL, headers LONGTEXT NOT NULL, queue_name VARCHAR(190) NOT NULL, created_at DATETIME NOT NULL, available_at DATETIME NOT NULL, delivered_at DATETIME DEFAULT NULL, INDEX IDX_75EA56E0FB7336F0 (queue_name), INDEX IDX_75EA56E0E3BD61CE (available_at), INDEX IDX_75EA56E016BA31DB (delivered_at), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE dinosaur ADD park_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE dinosaur ADD CONSTRAINT FK_DAEDC56E44990C25 FOREIGN KEY (park_id) REFERENCES park (id)'); + $this->addSql('CREATE INDEX IDX_DAEDC56E44990C25 ON dinosaur (park_id)'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE dinosaur DROP FOREIGN KEY FK_DAEDC56E44990C25'); + $this->addSql('DROP TABLE park'); + $this->addSql('DROP TABLE messenger_messages'); + $this->addSql('DROP INDEX IDX_DAEDC56E44990C25 ON dinosaur'); + $this->addSql('ALTER TABLE dinosaur DROP park_id'); + } +} diff --git a/src/Bus/CommandBus.php b/src/Bus/CommandBus.php new file mode 100644 index 0000000..e002dc5 --- /dev/null +++ b/src/Bus/CommandBus.php @@ -0,0 +1,23 @@ +handle($input); + } +} diff --git a/src/Command/ConsumeCommand.php b/src/Command/ConsumeCommand.php new file mode 100644 index 0000000..20f9ca8 --- /dev/null +++ b/src/Command/ConsumeCommand.php @@ -0,0 +1,49 @@ +setDescription('Dispatch some food comsumption messages.') + ->setHelp('This command allows you dispatch some food consumptions messages...') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $dinosaurs = $this->dinosaurRepository->findAll(); + + for ($i = 0; $i < 100; $i++) { + $randomDinoKey = array_rand($dinosaurs); + + $dinosaur = $dinosaurs[$randomDinoKey]; + + $consumeMessage = new Consume($dinosaur->getId(), $dinosaur->getName()); + + $this->bus->dispatch($consumeMessage); + } + + return Command::SUCCESS; + } +} diff --git a/src/Command/RefillCommand.php b/src/Command/RefillCommand.php new file mode 100644 index 0000000..fe27627 --- /dev/null +++ b/src/Command/RefillCommand.php @@ -0,0 +1,37 @@ +setDescription('Dispatch a food refill message.') + ->setHelp('This command allows you to dispatch a food refill command...') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $this->bus->dispatch(new Refill()); + + return Command::SUCCESS; + } +} diff --git a/src/Controller/DinosaursController.php b/src/Controller/DinosaursController.php index 4ced07c..14d7e43 100644 --- a/src/Controller/DinosaursController.php +++ b/src/Controller/DinosaursController.php @@ -2,9 +2,13 @@ namespace App\Controller; +use App\Bus\CommandBus; use App\Entity\Dinosaur; use App\Form\Type\DinosaurType; use App\Form\Type\SearchType; +use App\Message\Dinosaur\Create; +use App\Message\Dinosaur\Delete; +use App\Message\Dinosaur\Edit; use Doctrine\Persistence\ManagerRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -13,6 +17,11 @@ final class DinosaursController extends AbstractController { + public function __construct( + private CommandBus $bus + ) { + } + #[Route('/dinosaurs', name: 'app_list_dinosaurs')] public function list(Request $request, ManagerRegistry $doctrine): Response { @@ -58,20 +67,28 @@ public function single(string $id, ManagerRegistry $doctrine): Response } #[Route('/dinosaurs/create', name: 'app_create_dinosaur')] - public function create(Request $request, ManagerRegistry $doctrine): Response + public function create(Request $request): 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!'); + $data = $form->getData(); + + $result = $this->bus->dispatch(new Create( + name: $data->getName(), + gender: $data->getGender(), + eyesColor: $data->getEyesColor(), + age: $data->getAge(), + speciesId: $data->getSpecies()->getId(), + parkId: $data->getPark()->getId() + )); + + $this->addFlash('success', sprintf( + 'The dinosaur with id %s has been created!', + $result->id + )); return $this->redirectToRoute('app_list_dinosaurs'); } @@ -86,7 +103,7 @@ public function create(Request $request, ManagerRegistry $doctrine): Response name: 'app_edit_dinosaur', requirements: ['id' => '\d+'] )] - public function edit(Request $request, int $id, ManagerRegistry $doctrine): Response + public function edit(Request $request, string $id, ManagerRegistry $doctrine): Response { $dinosaur = $doctrine ->getRepository(Dinosaur::class) @@ -101,10 +118,16 @@ public function edit(Request $request, int $id, ManagerRegistry $doctrine): Resp $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $em = $doctrine->getManager(); - $dinosaur = $form->getData(); + $data = $form->getData(); - $em->flush(); + $this->bus->dispatch(new Edit( + id: $id, + name: $data->getName(), + gender: $data->getGender(), + eyesColor: $data->getEyesColor(), + age: $data->getAge(), + speciesId: $data->getSpecies()->getId() + )); $this->addFlash('success', 'The dinosaur has been edited!'); @@ -121,19 +144,9 @@ public function edit(Request $request, int $id, ManagerRegistry $doctrine): Resp name: 'app_remove_dinosaur', requirements: ['id' => '\d+'] )] - public function remove(int $id, ManagerRegistry $doctrine): Response + public function remove(string $id): 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->bus->dispatch(new Delete($id)); $this->addFlash('success', 'The dinosaur has been removed!'); diff --git a/src/Controller/SpeciesController.php b/src/Controller/SpeciesController.php index 7d356f8..54d0cc9 100644 --- a/src/Controller/SpeciesController.php +++ b/src/Controller/SpeciesController.php @@ -2,8 +2,12 @@ namespace App\Controller; +use App\Bus\CommandBus; use App\Entity\Species; use App\Form\Type\SpeciesType; +use App\Message\Species\Delete; +use App\Message\Species\Edit; +use App\Message\Species\Create; use Doctrine\Persistence\ManagerRegistry; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; @@ -12,6 +16,11 @@ final class SpeciesController extends AbstractController { + public function __construct( + private CommandBus $bus + ) { + } + #[Route('/species', name: 'app_list_species')] public function list(ManagerRegistry $doctrine): Response { @@ -32,13 +41,18 @@ public function create(Request $request, ManagerRegistry $doctrine): Response $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $em = $doctrine->getManager(); - $species = $form->getData(); + $data = $form->getData(); - $em->persist($species); - $em->flush(); + $result = $this->bus->dispatch(new Create( + name: $data->getName(), + feeding: $data->getFeeding(), + habitats: $data->getHabitats() + )); - $this->addFlash('success', 'The species has been created!'); + $this->addFlash('success', sprintf( + 'The species with id %s has been created!', + $result->id + )); return $this->redirectToRoute('app_list_species'); } @@ -53,7 +67,7 @@ public function create(Request $request, ManagerRegistry $doctrine): Response name: 'app_edit_species', requirements: ['id' => '\d+'] )] - public function edit(Request $request, int $id, ManagerRegistry $doctrine): Response + public function edit(Request $request, string $id, ManagerRegistry $doctrine): Response { $species = $doctrine ->getRepository(Species::class) @@ -68,10 +82,14 @@ public function edit(Request $request, int $id, ManagerRegistry $doctrine): Resp $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { - $em = $doctrine->getManager(); - $species = $form->getData(); + $data = $form->getData(); - $em->flush(); + $this->bus->dispatch(new Edit( + id: $id, + name: $data->getName(), + feeding: $data->getFeeding(), + habitats: $data->getHabitats() + )); $this->addFlash('success', 'The species has been edited!'); @@ -88,19 +106,9 @@ public function edit(Request $request, int $id, ManagerRegistry $doctrine): Resp name: 'app_remove_species', requirements: ['id' => '\d+'] )] - public function remove(int $id, ManagerRegistry $doctrine): Response + public function remove(string $id): 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->bus->dispatch(new Delete($id)); $this->addFlash('success', 'The species has been removed!'); diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index fc71111..adb9527 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -2,6 +2,7 @@ namespace App\DataFixtures; +use App\Entity\Park; use App\Entity\Dinosaur; use App\Entity\Species; use App\Entity\User; @@ -115,6 +116,10 @@ public function load(ObjectManager $manager): void $manager->flush(); + $park = new Park('Jurassic Park', 100); + $manager->persist($park); + $manager->flush(); + /** * Create dinosaurs. */ @@ -133,7 +138,8 @@ public function load(ObjectManager $manager): void $gender[array_rand($gender)], $speciesList[array_rand($speciesList)], rand(1, 40), - '#000000' + '#000000', + $park ); $manager->persist($dinosaur); diff --git a/src/Entity/Dinosaur.php b/src/Entity/Dinosaur.php index b11a447..8e324a9 100644 --- a/src/Entity/Dinosaur.php +++ b/src/Entity/Dinosaur.php @@ -11,7 +11,8 @@ public function __construct( private string $gender, private Species $species, private int $age, - private string $eyesColor + private string $eyesColor, + private Park $park, ) { } @@ -69,4 +70,14 @@ public function setEyesColor(string $eyesColor): void { $this->eyesColor = $eyesColor; } + + public function getPark(): Park + { + return $this->park; + } + + public function setPark(Park $park): void + { + $this->park = $park; + } } diff --git a/src/Entity/Park.php b/src/Entity/Park.php new file mode 100644 index 0000000..d81061c --- /dev/null +++ b/src/Entity/Park.php @@ -0,0 +1,59 @@ +name = $name; + $this->foodAmount = $foodAmount; + $this->dinosaurs = new ArrayCollection(); + } + + public function addDinosaurs(Dinosaur ...$dinosaur): void + { + $this->dinosaurs[] = $dinosaur; + } + + public function getId(): int + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function getFoodAmount(): int + { + return $this->foodAmount; + } + + public function setFoodAmount(int $foodAmount): void + { + $this->foodAmount = $foodAmount; + } + + public function getDinosaurs() + { + return $this->dinosaurs; + } +} diff --git a/src/Entity/Species.php b/src/Entity/Species.php index 61d5a90..b5e1f54 100644 --- a/src/Entity/Species.php +++ b/src/Entity/Species.php @@ -15,9 +15,6 @@ public function __construct( private array $habitats, private string $feeding, ) { - $this->name = $name; - $this->habitats = $habitats; - $this->feeding = $feeding; $this->dinosaurs = new ArrayCollection(); } diff --git a/src/Event/AbstractEvent.php b/src/Event/AbstractEvent.php new file mode 100644 index 0000000..f04d592 --- /dev/null +++ b/src/Event/AbstractEvent.php @@ -0,0 +1,18 @@ +id; + } +} diff --git a/src/Event/AsyncLowPriorityEvent.php b/src/Event/AsyncLowPriorityEvent.php new file mode 100644 index 0000000..e9ba284 --- /dev/null +++ b/src/Event/AsyncLowPriorityEvent.php @@ -0,0 +1,9 @@ +indexer->delete($event->getId()); + } +} diff --git a/src/EventHandler/Dinosaur/UpsertDinosaurSummary.php b/src/EventHandler/Dinosaur/UpsertDinosaurSummary.php new file mode 100644 index 0000000..752bf37 --- /dev/null +++ b/src/EventHandler/Dinosaur/UpsertDinosaurSummary.php @@ -0,0 +1,90 @@ +updateSummaryByDinosaur($event->getId()); + } + + #[AsMessageHandler] + public function handleDinosaurHasBeenUpdated(DinosaurHasBeenUpdated $event): void + { + $this->updateSummaryByDinosaur($event->getId()); + } + + #[AsMessageHandler] + public function handleFoodHasBeenConsumed(HasBeenConsumed $event): void + { + $this->updateSummariesByPark($event->getId()); + } + + #[AsMessageHandler] + public function handleFoodHasBeenRefilled(HasBeenRefilled $event): void + { + $this->updateSummariesByPark($event->getId()); + } + + #[AsMessageHandler] + public function handleSpeciesHasBeenUpdated(SpeciesHasBeenUpdated $event): void + { + $speciesId = $event->getId(); + + $species = $this->speciesRepository->find($speciesId); + + if (null === $species) { + throw new \RuntimeException(sprintf( + 'Species with id "%s" not found', + $speciesId + )); + } + + $dinosaurs = $this->dinosaurRepository->findBySpecies($species); + + foreach ($dinosaurs as $dinosaur) { + $this->indexer->indexFromDinosaur($dinosaur); + } + } + + private function updateSummaryByDinosaur(int $dinosaurId): void + { + $dinosaur = $this->dinosaurRepository->find($dinosaurId); + + if (null === $dinosaur) { + throw new \RuntimeException(sprintf('Dinosaur with id "%s" not found', $dinosaurId)); + } + + $this->indexer->indexFromDinosaur($dinosaur); + } + + private function updateSummariesByPark(int $parkId): void + { + $dinosaurs = $this->dinosaurRepository->findByPark($parkId); + + foreach ($dinosaurs as $dinosaur) { + $this->indexer->indexFromDinosaur($dinosaur); + } + } +} diff --git a/src/EventListener/WorkerListener.php b/src/EventListener/WorkerListener.php new file mode 100644 index 0000000..088f6a9 --- /dev/null +++ b/src/EventListener/WorkerListener.php @@ -0,0 +1,88 @@ +getWorker()->getMetadata()->getTransportNames(); + + $this->logger->log(LogLevel::NOTICE, sprintf( + 'Worker started. Transports priority : [%s]', + implode(', ', $transports) + )); + } + + public function onWorkerStoppedEvent(WorkerStoppedEvent $event) + { + $this->logger->log(LogLevel::NOTICE, 'Worker stopped'); + } + + public function onWorkerMessageReceivedEvent(WorkerMessageReceivedEvent $event) + { + $envelope = $event->getEnvelope(); + + $message = $envelope->getMessage(); + $messageClass = get_class($message); + + $this->logger->log(LogLevel::NOTICE, sprintf('Received message %s', $messageClass)); + } + + public function onWorkerMessageHandledEvent(WorkerMessageHandledEvent $event) + { + $envelope = $event->getEnvelope(); + + $handledStamp = $envelope->last(HandledStamp::class); + + if (null === $handledStamp) { + return; + } + + $handlerName = $handledStamp->getHandlerName(); + + $message = $envelope->getMessage(); + $messageClass = get_class($message); + + $this->logger->log(LogLevel::NOTICE, sprintf('Message %s handled by %s', $messageClass, $handlerName)); + } + + public function onWorkerMessageFailedEvent(WorkerMessageFailedEvent $event) + { + $envelope = $event->getEnvelope(); + + $message = $envelope->getMessage(); + $messageClass = get_class($message); + + $this->logger->log(LogLevel::CRITICAL, sprintf('Message %s failed', $messageClass)); + } + + public function onWorkerRunningEvent() + { + $this->logger->log(LogLevel::NOTICE, 'Worker is running. Waiting for messages...'); + } +} diff --git a/src/Form/Type/DinosaurType.php b/src/Form/Type/DinosaurType.php index 9640754..73c0851 100644 --- a/src/Form/Type/DinosaurType.php +++ b/src/Form/Type/DinosaurType.php @@ -3,6 +3,7 @@ namespace App\Form\Type; use App\Entity\Dinosaur; +use App\Entity\Park; use App\Entity\Species; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; @@ -30,6 +31,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void 'class' => Species::class, 'choice_label' => 'name', ]) + ->add('park', EntityType::class, [ + 'class' => Park::class, + 'choice_label' => 'name' + ]) ->add('age', NumberType::class) ->add('eyesColor', ColorType::class) ->add('submit', SubmitType::class); @@ -46,6 +51,7 @@ public function configureOptions(OptionsResolver $resolver): void $form->get('species')->getData(), $form->get('age')->getData(), $form->get('eyesColor')->getData(), + $form->get('park')->getData() ); }, ]); diff --git a/src/Indexer.php b/src/Indexer.php new file mode 100644 index 0000000..80be302 --- /dev/null +++ b/src/Indexer.php @@ -0,0 +1,48 @@ +getSpecies(); + $park = $dinosaur->getPark(); + + $this->client->index([ + 'index' => self::INDEX_NAME, + 'type' => '_doc', + 'id' => $dinosaur->getId(), + 'body' => [ + 'name' => $dinosaur->getName(), + 'age' => $dinosaur->getAge(), + 'park_food_amount' => $park->getFoodAmount(), + 'park_name' => $park->getName(), + 'species_name' => $species->getName(), + 'habitats' => $species->getHabitats(), + 'feeding'=> $species->getFeeding(), + ], + ]); + } + + public function delete(int $id) + { + $this->client->delete([ + 'index' => self::INDEX_NAME, + 'type' => '_doc', + 'id' => $id, + ]); + } +} diff --git a/src/Message/Dinosaur/Create.php b/src/Message/Dinosaur/Create.php new file mode 100644 index 0000000..5ccc485 --- /dev/null +++ b/src/Message/Dinosaur/Create.php @@ -0,0 +1,16 @@ +speciesRepository->find($message->speciesId)) { + throw new NotFoundHttpException("Species with id {$message->speciesId} not found"); + } + + if (!$park = $this->parkRepository->find($message->parkId)) { + throw new NotFoundHttpException("Park with id {$message->parkId} not found"); + } + + $dino = new Dinosaur( + name: $message->name, + gender: $message->gender, + species: $species, + age: $message->age, + eyesColor: $message->eyesColor, + park: $park + ); + + $this->dinosaurRepository->add($dino, flush: true); + + $envelop = new Envelope(new HasBeenCreated($dino->getId())); + + $this + ->eventBus + ->dispatch($envelop->with(new DispatchAfterCurrentBusStamp())) + ; + + return new CreateMessageResult($dino->getId()); + } +} diff --git a/src/MessageHandler/Dinosaur/Delete.php b/src/MessageHandler/Dinosaur/Delete.php new file mode 100644 index 0000000..6e7495c --- /dev/null +++ b/src/MessageHandler/Dinosaur/Delete.php @@ -0,0 +1,43 @@ +dinosaurRepository->find($message->id)) { + throw new NotFoundHttpException("Dinosaur with id {$message->id} not found"); + } + + $this->entityManager->remove($dinosaur); + + $envelop = new Envelope( + new HasBeenDeleted($message->id) + ); + + $this->eventBus->dispatch( + $envelop->with(new DispatchAfterCurrentBusStamp()) + ); + } +} diff --git a/src/MessageHandler/Dinosaur/Edit.php b/src/MessageHandler/Dinosaur/Edit.php new file mode 100644 index 0000000..64ab1de --- /dev/null +++ b/src/MessageHandler/Dinosaur/Edit.php @@ -0,0 +1,47 @@ +dinosaurRepository->find($message->id)) { + throw new NotFoundHttpException("Dinosaur with id {$message->id} not found"); + } + + if (!$species = $this->speciesRepository->find($message->speciesId)) { + throw new NotFoundHttpException("Species with id {$message->id} not found"); + } + + $dinosaur->setName($message->name); + $dinosaur->setEyesColor($message->eyesColor); + $dinosaur->setAge($message->age); + $dinosaur->setSpecies($species); + + $envelop = new Envelope(new HasBeenUpdated($dinosaur->getId())); + + $this + ->eventBus + ->dispatch($envelop->with(new DispatchAfterCurrentBusStamp())) + ; + } +} diff --git a/src/MessageHandler/Food/Consume.php b/src/MessageHandler/Food/Consume.php new file mode 100644 index 0000000..560389b --- /dev/null +++ b/src/MessageHandler/Food/Consume.php @@ -0,0 +1,65 @@ +dinosaurId; + + $dinosaursRepository = $this->em->getRepository(Dinosaur::class); + + /** @var Dinosaur $dinosaur */ + $dinosaur = $dinosaursRepository->find($dinosaurId); + + $park = $dinosaur->getPark(); + + $consumedAmout = random_int(1, 10); + + if ($consumedAmout > $park->getFoodAmount()) { + throw new DomainException(sprintf( + 'Not enough food to feed %s', + $dinosaur->getName() + )); + } + + $this->logger->info(sprintf( + '%s is consuming %d stacks of food. He needs to rest...', + $dinosaur->getName(), + $consumedAmout + )); + + sleep($consumedAmout); + + $park->setFoodAmount($park->getFoodAmount() - $consumedAmout); + + $envelop = new Envelope(new HasBeenConsumed($park->getId())); + + $this + ->eventBus + ->dispatch($envelop->with(new DispatchAfterCurrentBusStamp())) + ; + } +} diff --git a/src/MessageHandler/Food/Refill.php b/src/MessageHandler/Food/Refill.php new file mode 100644 index 0000000..e84d4fd --- /dev/null +++ b/src/MessageHandler/Food/Refill.php @@ -0,0 +1,54 @@ +logger->info('Refilling food'); + + $parkRepository = $this->entityManager->getRepository(Park::class); + + /** @var Park[] $parks */ + $parks = $parkRepository->findAll(); + + $dinosaurIsAttacking = random_int(0, 10); + + if ($dinosaurIsAttacking < 5) { + throw new DomainException('Dinosaur is attacking cannot refill food'); + } + + foreach ($parks as $park) { + $park->setFoodAmount(100); + } + + $envelop = new Envelope(new HasBeenRefilled($park->getId())); + + $this + ->eventBus + ->dispatch($envelop->with(new DispatchAfterCurrentBusStamp())) + ; + } +} diff --git a/src/MessageHandler/Species/Create.php b/src/MessageHandler/Species/Create.php new file mode 100644 index 0000000..02c1185 --- /dev/null +++ b/src/MessageHandler/Species/Create.php @@ -0,0 +1,44 @@ +name, + habitats: $message->habitats, + feeding: $message->feeding + ); + + $this->speciesRepository->add($species, flush: true); + + $envelop = new Envelope(new HasBeenCreated( + $species->getId() + )); + + $this + ->eventBus + ->dispatch($envelop->with(new DispatchAfterCurrentBusStamp())); + + return new CreateMessageResult($species->getId()); + } +} diff --git a/src/MessageHandler/Species/Delete.php b/src/MessageHandler/Species/Delete.php new file mode 100644 index 0000000..54b24ba --- /dev/null +++ b/src/MessageHandler/Species/Delete.php @@ -0,0 +1,29 @@ +speciesRepository->find($message->id)) { + throw new NotFoundHttpException("Species with id {$message->id} not found"); + } + + $this->entityManager->remove($species); + } +} diff --git a/src/MessageHandler/Species/Edit.php b/src/MessageHandler/Species/Edit.php new file mode 100644 index 0000000..a138739 --- /dev/null +++ b/src/MessageHandler/Species/Edit.php @@ -0,0 +1,42 @@ +speciesRepository->find($message->id)) { + throw new NotFoundHttpException("Species with id {$message->id} not found"); + } + + $species->setName($message->name); + $species->setFeeding($message->feeding); + $species->setHabitats($message->habitats); + + $envelop = new Envelope(new HasBeenUpdated($message->id)); + + $this + ->eventBus + ->dispatch($envelop->with(new DispatchAfterCurrentBusStamp())) + ; + } +} diff --git a/src/MessageResults/Dinosaur/Create.php b/src/MessageResults/Dinosaur/Create.php new file mode 100644 index 0000000..9a317e2 --- /dev/null +++ b/src/MessageResults/Dinosaur/Create.php @@ -0,0 +1,13 @@ +getMessage(); + + if (!$message instanceof Lockable) { + return $stack->next()->handle($envelope, $stack); + } + + if ([] === $envelope->all(LockStamp::class)) { + $envelope = $envelope->with(new LockStamp( + $message->dinosaurId + )); + + return $stack->next()->handle($envelope, $stack); + } + + /** @var LockStamp $lockStamp */ + $lockStamp = $envelope->last(LockStamp::class); + + $lock = $this->lockFactory->createLock((string) $lockStamp->lockKey); + + if ($lock->acquire()) { + $return = $stack->next()->handle($envelope, $stack); + + $lock->release(); + + return $return; + } + + throw new RuntimeException("Unable to acquire the lock for {$message->dinosaurName}"); + } +} diff --git a/src/Repository/DinosaurRepository.php b/src/Repository/DinosaurRepository.php index 1016b70..d902df2 100644 --- a/src/Repository/DinosaurRepository.php +++ b/src/Repository/DinosaurRepository.php @@ -13,6 +13,14 @@ public function __construct(ManagerRegistry $registry) parent::__construct($registry, Dinosaur::class); } + public function add(Dinosaur $dinosaur, bool $flush = false): void + { + $this->getEntityManager()->persist($dinosaur); + if ($flush) { + $this->getEntityManager()->flush(); + } + } + public function search(?string $q): array { if (null === $q) { diff --git a/src/Repository/ParkRepository.php b/src/Repository/ParkRepository.php new file mode 100644 index 0000000..ffd960b --- /dev/null +++ b/src/Repository/ParkRepository.php @@ -0,0 +1,15 @@ +getEntityManager()->persist($species); + if ($flush) { + $this->getEntityManager()->flush(); + } + } } diff --git a/src/Stamp/LockStamp.php b/src/Stamp/LockStamp.php new file mode 100644 index 0000000..587381d --- /dev/null +++ b/src/Stamp/LockStamp.php @@ -0,0 +1,13 @@ +