diff --git a/composer.json b/composer.json index 8e345e4..13dd46d 100644 --- a/composer.json +++ b/composer.json @@ -59,8 +59,6 @@ "symfony/debug-bundle": "^5.3", "symfony/maker-bundle": "^1.14", "symfony/monolog-bundle": "^3.0", - "symfony/stopwatch": "^5.2", - "symfony/web-profiler-bundle": "^5.2", "symfony/stopwatch": "^5.3", "symfony/web-profiler-bundle": "^5.3", "theofidry/psysh-bundle": "^4.3", diff --git a/composer.lock b/composer.lock index 08cf17b..168c373 100644 --- a/composer.lock +++ b/composer.lock @@ -3962,16 +3962,16 @@ }, { "name": "symfony/flex", - "version": "v1.15.3", + "version": "v1.15.4", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "f16f10772422ace36dc76d5d5c7a682c8b925c0c" + "reference": "9a22ef2a75609a4d3717db784d923a7a6b347bc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/f16f10772422ace36dc76d5d5c7a682c8b925c0c", - "reference": "f16f10772422ace36dc76d5d5c7a682c8b925c0c", + "url": "https://api.github.com/repos/symfony/flex/zipball/9a22ef2a75609a4d3717db784d923a7a6b347bc5", + "reference": "9a22ef2a75609a4d3717db784d923a7a6b347bc5", "shasum": "" }, "require": { @@ -4010,7 +4010,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v1.15.3" + "source": "https://github.com/symfony/flex/tree/v1.15.4" }, "funding": [ { @@ -4026,7 +4026,7 @@ "type": "tidelift" } ], - "time": "2021-09-06T12:45:00+00:00" + "time": "2021-09-13T14:49:33+00:00" }, { "name": "symfony/framework-bundle", @@ -8887,16 +8887,16 @@ }, { "name": "mockery/mockery", - "version": "1.4.3", + "version": "1.4.4", "source": { "type": "git", "url": "https://github.com/mockery/mockery.git", - "reference": "d1339f64479af1bee0e82a0413813fe5345a54ea" + "reference": "e01123a0e847d52d186c5eb4b9bf58b0c6d00346" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mockery/mockery/zipball/d1339f64479af1bee0e82a0413813fe5345a54ea", - "reference": "d1339f64479af1bee0e82a0413813fe5345a54ea", + "url": "https://api.github.com/repos/mockery/mockery/zipball/e01123a0e847d52d186c5eb4b9bf58b0c6d00346", + "reference": "e01123a0e847d52d186c5eb4b9bf58b0c6d00346", "shasum": "" }, "require": { @@ -8953,30 +8953,30 @@ ], "support": { "issues": "https://github.com/mockery/mockery/issues", - "source": "https://github.com/mockery/mockery/tree/1.4.3" + "source": "https://github.com/mockery/mockery/tree/1.4.4" }, - "time": "2021-02-24T09:51:49+00:00" + "time": "2021-09-13T15:28:59+00:00" }, { "name": "monolog/monolog", - "version": "2.3.2", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "71312564759a7db5b789296369c1a264efc43aad" + "reference": "3962ebfe206ac7ce6c754c79e2fee0c64bf1818d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/71312564759a7db5b789296369c1a264efc43aad", - "reference": "71312564759a7db5b789296369c1a264efc43aad", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/3962ebfe206ac7ce6c754c79e2fee0c64bf1818d", + "reference": "3962ebfe206ac7ce6c754c79e2fee0c64bf1818d", "shasum": "" }, "require": { "php": ">=7.2", - "psr/log": "^1.0.1" + "psr/log": "^1.0.1 || ^2.0" }, "provide": { - "psr/log-implementation": "1.0.0" + "psr/log-implementation": "1.0.0 || 2.0.0" }, "require-dev": { "aws/aws-sdk-php": "^2.4.9 || ^3.0", @@ -8990,8 +8990,7 @@ "phpstan/phpstan": "^0.12.91", "phpunit/phpunit": "^8.5", "predis/predis": "^1.1", - "rollbar/rollbar": "^1.3", - "ruflin/elastica": ">=0.90 <7.0.1", + "ruflin/elastica": ">=0.90@dev", "swiftmailer/swiftmailer": "^5.3|^6.0" }, "suggest": { @@ -8999,8 +8998,11 @@ "doctrine/couchdb": "Allow sending log messages to a CouchDB server", "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", "ext-mbstring": "Allow to work properly with unicode symbols", "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", @@ -9039,7 +9041,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.3.2" + "source": "https://github.com/Seldaek/monolog/tree/2.3.3" }, "funding": [ { @@ -9051,7 +9053,7 @@ "type": "tidelift" } ], - "time": "2021-07-23T07:42:52+00:00" + "time": "2021-09-14T18:40:13+00:00" }, { "name": "myclabs/deep-copy", @@ -13341,5 +13343,5 @@ "ext-pdo": "*" }, "platform-dev": [], - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.1.0" } diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index 9f7ddfa..370987c 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -13,7 +13,7 @@ doctrine: mappings: App: is_bundle: false - type: annotation + type: attribute dir: '%kernel.project_dir%/src/App/Entity' prefix: 'App\Entity' alias: App @@ -25,7 +25,7 @@ doctrine: alias: CheeperDomainModel Architecture: is_bundle: false - type: annotation + type: attribute dir: '%kernel.project_dir%/src/Architecture' prefix: 'Architecture' alias: 'Architecture' diff --git a/config/services.yaml b/config/services.yaml index 91fe10c..00b8830 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -13,10 +13,14 @@ services: bind: Cheeper\DomainModel\Cheep\Cheeps $cheeps: '@Cheeper\Infrastructure\Persistence\DoctrineOrmCheeps' Cheeper\DomainModel\Author\Authors $authors: '@Cheeper\Infrastructure\Persistence\DoctrineOrmAuthors' + Cheeper\DomainModel\Author\Authors $authorsRepository: '@Cheeper\Infrastructure\Persistence\DoctrineOrmAuthors' Cheeper\DomainModel\Follow\Follows $follows: '@Cheeper\Infrastructure\Persistence\DoctrineOrmFollows' Symfony\Component\Messenger\MessageBusInterface $commandBus: "@command.bus" Symfony\Component\Messenger\MessageBusInterface $queryBus: "@query.bus" Symfony\Component\Messenger\MessageBusInterface $eventBus: "@event.bus" + Cheeper\Chapter6\Application\Event\EventBus: '@Cheeper\Chapter6\Infrastructure\Application\Event\SymfonyEventBus' + Cheeper\Chapter5\Application\Query\QueryBus: '@Cheeper\Chapter5\Infrastructure\Application\Query\SymfonyQueryBus' + Architecture\CQRS\App\Repository\FollowersRepository: '@Architecture\CQRS\Infrastructure\Persistence\Doctrine\DoctrineFollowersRepository' # makes classes in src/ available to be used as services # this creates a service per class whose id is the fully-qualified class name @@ -52,28 +56,23 @@ services: tags: - { name: messenger.message_handler, bus: command.bus } - Cheeper\Chapter5\Application\Query\QueryBus: - class: 'Cheeper\Chapter5\Infrastructure\Application\Query\SymfonyQueryBus' - - Cheeper\Chapter5\Application\Query\CountFollowersHandlerWithRedisAccess\CountFollowersHandler: + Cheeper\Chapter5\Application\Query\: + resource: '../src/Cheeper/Chapter5/Application/Query/**/*Handler.php' + autoconfigure: false tags: - { name: messenger.message_handler, bus: query.bus } - arguments: - - '@Predis\ClientInterface' - # CHAPTER 6 + Cheeper\Chapter6\Infrastructure\: + resource: '../src/Cheeper/Chapter6/Infrastructure/**/*.php' + +# CHAPTER 5 + Cheeper\Chapter5\Infrastructure\Application\Query\SymfonyQueryBus: ~ + Architecture\CQRS\Infrastructure\Persistence\Doctrine\DoctrineFollowersRepository: ~ + +# CHAPTER 6 # Cheeper\Chapter6\Infrastructure\Application\Projector\Author\SymfonyAuthorFollowedHandler: # resource: '../src/Cheeper/Infrastructure/**/*.php' - Cheeper\Chapter6\Application\Command\EventBus: - class: 'Cheeper\Chapter6\Infrastructure\Application\Command\SymfonyEventBus' - - Cheeper\DomainModel\Follow\Follows: - class: 'Cheeper\Infrastructure\Persistence\DoctrineOrmFollows' - - Cheeper\DomainModel\Author\Authors: - class: 'Cheeper\Infrastructure\Persistence\DoctrineOrmAuthors' - Cheeper\Chapter6\Application\Projector\Author\CountFollowerProjector: ~ Cheeper\Chapter6\Application\Command\Author\WithDomainEvents\FollowHandler: diff --git a/src/Architecture/CQRS/App/Entity/Followers.php b/src/Architecture/CQRS/App/Entity/Followers.php index f9ea954..fc204b1 100644 --- a/src/Architecture/CQRS/App/Entity/Followers.php +++ b/src/Architecture/CQRS/App/Entity/Followers.php @@ -8,29 +8,19 @@ use Architecture\CQRS\Infrastructure\Persistence\Doctrine\DoctrineFollowersRepos use Doctrine\ORM\Mapping as ORM; use Ramsey\Uuid\UuidInterface; -/** - * @ORM\Entity( - * repositoryClass=DoctrineFollowersRepository::class - * ) - * - * @ORM\Table(name="architecture_followers") - */ +#[ORM\Entity(repositoryClass: DoctrineFollowersRepository::class)] +#[ORM\Table(name: "architecture_followers")] class Followers { - /** - * @ORM\Column(type="uuid_binary") - * @ORM\GeneratedValue(strategy="NONE") - * @ORM\Id() - */ - private UuidInterface $userId; + public function __construct( + #[ORM\Column(type: "uuid_binary")] + #[ORM\GeneratedValue(strategy: "NONE")] + #[ORM\Id] + private UuidInterface $userId, - /** @ORM\Column(type="integer") */ - private int $followers; - - public function __construct(UuidInterface $userId, int $followers) - { - $this->userId = $userId; - $this->followers = $followers; + #[ORM\Column(type: "integer")] + private int $followers + ) { } public function userId(): UuidInterface diff --git a/src/Architecture/CQRS/App/Repository/FollowersRepository.php b/src/Architecture/CQRS/App/Repository/FollowersRepository.php new file mode 100644 index 0000000..e549ee8 --- /dev/null +++ b/src/Architecture/CQRS/App/Repository/FollowersRepository.php @@ -0,0 +1,13 @@ + */ -final class DoctrineFollowersRepository extends ServiceEntityRepository +final class DoctrineFollowersRepository extends ServiceEntityRepository implements FollowersRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, Followers::class); } - public function ofAuthorId(UuidInterface $authorId): ?Followers + public function ofAuthorId(AuthorId $authorId): ?Followers { return $this->find($authorId->toString()); } diff --git a/src/Cheeper/Chapter5/Application/Query/CountFollowersHandlerWithRepositoriesAccess/CountFollowersHandler.php b/src/Cheeper/Chapter5/Application/Query/CountFollowersHandlerWithRepositoriesAccess/CountFollowersHandler.php index 1095228..94bcc91 100644 --- a/src/Cheeper/Chapter5/Application/Query/CountFollowersHandlerWithRepositoriesAccess/CountFollowersHandler.php +++ b/src/Cheeper/Chapter5/Application/Query/CountFollowersHandlerWithRepositoriesAccess/CountFollowersHandler.php @@ -4,7 +4,7 @@ declare(strict_types=1); namespace Cheeper\Chapter5\Application\Query\CountFollowersHandlerWithRepositoriesAccess; -use Architecture\CQRS\App\Entity\Followers; +use Architecture\CQRS\App\Repository\FollowersRepository; use Cheeper\Chapter5\Application\Query\CountFollowers; use Cheeper\Chapter5\Application\Query\CountFollowersResponse; use Cheeper\DomainModel\Author\AuthorDoesNotExist; @@ -15,7 +15,7 @@ use Cheeper\DomainModel\Author\Authors; final class CountFollowersHandler { public function __construct( - private Followers $followersRepository, + private FollowersRepository $followersRepository, private Authors $authorsRepository ) { } @@ -29,7 +29,7 @@ final class CountFollowersHandler throw AuthorDoesNotExist::withAuthorIdOf($authorId); } - $followersCount = count($this->followersRepository->ofAuthorId($authorId)); + $followersCount = $this->followersRepository->ofAuthorId($authorId)->followers(); // Other option would be with a counter method in the Repository // $followersCount = $this->followersRepository->countOfAuthorId($authorId)); diff --git a/src/Cheeper/Chapter6/Application/Command/Author/WithDomainEvents/FollowHandler.php b/src/Cheeper/Chapter6/Application/Command/Author/WithDomainEvents/FollowHandler.php index dafe9fb..a4c2825 100644 --- a/src/Cheeper/Chapter6/Application/Command/Author/WithDomainEvents/FollowHandler.php +++ b/src/Cheeper/Chapter6/Application/Command/Author/WithDomainEvents/FollowHandler.php @@ -16,8 +16,8 @@ use Cheeper\DomainModel\Follow\Follows; final class FollowHandler { public function __construct( - private Authors $authorsRepository, - private Follows $followsRepository, + private Authors $authors, + private Follows $follows, // leanpub-start-insert private EventBus $eventBus // leanpub-end-insert @@ -32,13 +32,13 @@ final class FollowHandler $fromAuthor = $this->tryToFindTheAuthorOfId($fromAuthorId); $toAuthor = $this->tryToFindTheAuthorOfId($toAuthorId); - $follow = $this->followsRepository->ofFromAuthorIdAndToAuthorId($fromAuthorId, $toAuthorId); + $follow = $this->follows->ofFromAuthorIdAndToAuthorId($fromAuthorId, $toAuthorId); if (null !== $follow) { return; } $follow = $fromAuthor->followAuthorId($toAuthor->authorId()); - $this->followsRepository->save($follow); + $this->follows->save($follow); // leanpub-start-insert $this->eventBus->notifyAll($follow->domainEvents()); @@ -47,7 +47,7 @@ final class FollowHandler private function tryToFindTheAuthorOfId(AuthorId $authorId): Author { - $author = $this->authorsRepository->ofId($authorId); + $author = $this->authors->ofId($authorId); if (null === $author) { throw AuthorDoesNotExist::withAuthorIdOf($authorId); }