diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index 47304e7..f3803f7 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -12,58 +12,21 @@ jobs:
fail-fast: false
matrix:
include:
- - php: '5.5'
- symfony: '2.8.*'
- doctrine: '2.4.*'
- phpunit: '4.8.*'
- - php: '5.6'
- symfony: '2.8.*'
- doctrine: '2.4.*'
- phpunit: '4.8.*'
- - php: '7.0'
- symfony: '2.8.*'
- doctrine: '2.4.*'
- phpunit: '4.8.*'
- - php: '7.1'
- symfony: '2.8.*'
- doctrine: '2.4.*'
- phpunit: '6.5.*'
- - php: '7.2'
- symfony: '2.8.*'
- doctrine: '2.4.*'
- phpunit: '6.5.*'
- - php: '7.3'
- symfony: '3.4.*'
- doctrine: '2.6.*'
- phpunit: '6.5.*'
- - php: '7.4'
- symfony: '3.4.*'
- doctrine: '2.6.*'
- phpunit: '6.5.*'
- - php: '5.5'
- symfony: '2.8.*'
- doctrine: '2.5.*'
- phpunit: '4.8.*'
- php: '7.4'
symfony: '4.4.*'
doctrine: '2.6.*'
- phpunit: '6.5.*'
- php: '7.4'
symfony: '5.*'
doctrine: '2.7.*'
- phpunit: '6.5.*'
- php: '7.4'
symfony: '4.4.*'
doctrine: '2.7.*'
- phpunit: '6.5.*'
- php: '7.4'
symfony: '4.4.*'
doctrine: '2.8.*'
- phpunit: '6.5.*'
-# # require PHPUnit >= 8.5.12
-# - php: '8.0'
-# symfony: '5.*'
-# doctrine: '2.*'
+ - php: '8.0'
+ symfony: '5.*'
+ doctrine: '2.*'
steps:
- name: Checkout
@@ -82,9 +45,6 @@ jobs:
- name: Install Doctrine
run: composer require doctrine/orm:"${{ matrix.doctrine }}" --no-update
- - name: Install PHPUnit
- run: composer require phpunit/phpunit:"${{ matrix.phpunit }}" --no-update
-
- name: "Install Composer dependencies (highest)"
uses: "ramsey/composer-install@v1"
with:
@@ -95,6 +55,7 @@ jobs:
run: vendor/bin/phpunit --coverage-clover build/coverage-clover.xml
- name: Send coverage results to Scrutinizer CI
+ if: ${{ matrix.php != '8.0' }}
run: |
wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover build/coverage-clover.xml
diff --git a/.php_cs.dist b/.php_cs.dist
index 438e574..a250992 100644
--- a/.php_cs.dist
+++ b/.php_cs.dist
@@ -1,4 +1,5 @@
true,
+ 'header_comment' => [
+ 'comment_type' => 'PHPDoc',
+ 'header' => $header,
+ ],
+ 'single_line_throw' => false,
+ 'blank_line_after_opening_tag' => false,
+ 'yoda_style' => false,
+ 'ordered_imports' => [
+ 'sort_algorithm' => 'alpha',
+ ],
+];
+
+$finder = PhpCsFixer\Finder::create()
+ ->in(__DIR__.'/src')
+ ->in(__DIR__.'/tests')
+ ->notPath('bootstrap.php')
+;
+
return PhpCsFixer\Config::create()
- ->setRules([
- '@Symfony' => true,
- 'array_syntax' => ['syntax' => 'short'],
- 'header_comment' => [
- 'comment_type' => 'PHPDoc',
- 'header' => $header,
- ],
- 'class_definition' => [
- 'multi_line_extends_each_single_line' => true,
- ],
- 'no_superfluous_phpdoc_tags' => false,
- 'single_line_throw' => false,
- 'blank_line_after_opening_tag' => false,
- 'yoda_style' => false,
- 'phpdoc_no_empty_return' => false,
- 'ordered_imports' => [
- 'sort_algorithm' => 'alpha',
- ],
- 'list_syntax' => [
- 'syntax' => 'short',
- ],
- ])
- ->setFinder(
- PhpCsFixer\Finder::create()
- ->in(__DIR__.'/src')
- ->in(__DIR__.'/tests')
- ->notPath('bootstrap.php')
- )
- ;
\ No newline at end of file
+ ->setRules($rules)
+ ->setFinder($finder)
+;
diff --git a/README.md b/README.md
index 0587b88..c9b4262 100644
--- a/README.md
+++ b/README.md
@@ -11,8 +11,6 @@ Domain event bundle
Bundle to create the domain layer of your [Domain-driven design (DDD)](https://en.wikipedia.org/wiki/Domain-driven_design) application.
-This [Symfony](https://symfony.com/) bundle is a wrapper for [gpslab/domain-event](https://github.com/gpslab/domain-event), look it for more details.
-
Installation
------------
@@ -22,73 +20,36 @@ Pretty simple with [Composer](http://packagist.org), run:
composer req gpslab/domain-event-bundle
```
-Configuration
--------------
-
-Example configuration
-
-```yml
-gpslab_domain_event:
- # Event bus service
- # Support 'listener_located', 'queue' or a custom service
- # As a default used 'listener_located'
- bus: 'listener_located'
-
- # Event queue service
- # Support 'pull_memory', 'subscribe_executing' or a custom service
- # As a default used 'pull_memory'
- queue: 'pull_memory'
-
- # Event listener locator
- # Support 'symfony', 'container', 'direct_binding' or custom service
- # As a default used 'symfony'
- locator: 'symfony'
-
- # Publish domain events post a Doctrine flush event
- # As a default used 'false'
- publish_on_flush: true
-```
-
Usage
-----
Create a domain event
```php
-use GpsLab\Domain\Event\Event
+use Symfony\Contracts\EventDispatcher\Event;
-class PurchaseOrderCreatedEvent implements Event
+final class PurchaseOrderCreatedEvent extends Event
{
- private $customer_id;
- private $create_at;
+ public CustomerId $customer_id;
+ public \DateTimeImmutable $create_at;
public function __construct(CustomerId $customer_id, \DateTimeImmutable $create_at)
{
$this->customer_id = $customer_id;
$this->create_at = $create_at;
}
-
- public function customerId(): CustomerId
- {
- return $this->customer_id;
- }
-
- public function createAt(): \DateTimeImmutable
- {
- return $this->create_at;
- }
}
```
Raise your event
```php
-use GpsLab\Domain\Event\Aggregator\AbstractAggregateEvents;
+use GpsLab\Bundle\DomainEvent\Event\Aggregator\AbstractAggregateEvents;
-final class PurchaseOrder extends AbstractAggregateEvents
+class PurchaseOrder extends AbstractAggregateEvents
{
- private $customer_id;
- private $create_at;
+ private CustomerId $customer_id;
+ private \DateTimeImmutable $create_at;
public function __construct(CustomerId $customer_id)
{
@@ -100,136 +61,24 @@ final class PurchaseOrder extends AbstractAggregateEvents
}
```
-Create listener
+Create event subscriber
```php
-use GpsLab\Domain\Event\Event;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-class SendEmailOnPurchaseOrderCreated
+class SendEmailOnPurchaseOrderCreated implements EventSubscriberInterface
{
- private $mailer;
+ private \Swift_Mailer $mailer;
public function __construct(\Swift_Mailer $mailer)
{
$this->mailer = $mailer;
}
- public function onPurchaseOrderCreated(PurchaseOrderCreatedEvent $event): void
- {
- $message = $this->mailer
- ->createMessage()
- ->setTo('recipient@example.com')
- ->setBody(sprintf(
- 'Purchase order created at %s for customer #%s',
- $event->createAt()->format('Y-m-d'),
- $event->customerId()
- ));
-
- $this->mailer->send($message);
- }
-}
-```
-
-Register event listener
-
-```yml
-services:
- SendEmailOnPurchaseOrderCreated:
- arguments: [ '@mailer' ]
- tags:
- - { name: domain_event.listener, event: PurchaseOrderCreatedEvent, method: onPurchaseOrderCreated }
-```
-
-Publish events in listener
-
-```php
-use GpsLab\Domain\Event\Bus\EventBus;
-
-// get event bus from DI container
-$bus = $this->get(EventBus::class);
-
-// do what you need to do on your Domain
-$purchase_order = new PurchaseOrder(new CustomerId(1));
-
-// this will clear the list of event in your AggregateEvents so an Event is trigger only once
-$events = $purchase_order->pullEvents();
-
-// You can have more than one event at a time.
-foreach($events as $event) {
- $bus->publish($event);
-}
-
-// You can use one method
-//$bus->pullAndPublish($purchase_order);
-```
-
-Listener method name
---------------------
-
-You do not need to specify the name of the event handler method. By default, the
-[__invoke](http://php.net/manual/en/language.oop5.magic.php#object.invoke) method is used.
-
-
-```php
-use GpsLab\Domain\Event\Event;
-
-class SendEmailOnPurchaseOrderCreated
-{
- private $mailer;
-
- public function __construct(\Swift_Mailer $mailer)
- {
- $this->mailer = $mailer;
- }
-
- public function __invoke(PurchaseOrderCreatedEvent $event): void
- {
- $message = $this->mailer
- ->createMessage()
- ->setTo('recipient@example.com')
- ->setBody(sprintf(
- 'Purchase order created at %s for customer #%s',
- $event->createAt()->format('Y-m-d'),
- $event->customerId()
- ));
-
- $this->mailer->send($message);
- }
-}
-```
-
-Register event listener
-
-```yml
-services:
- SendEmailOnPurchaseOrderCreated:
- arguments: [ '@mailer' ]
- tags:
- - { name: domain_event.listener, event: PurchaseOrderCreatedEvent }
-```
-
-Event subscribers
------------------
-
-Create subscriber
-
-```php
-use GpsLab\Domain\Event\Event;
-use GpsLab\Domain\Event\Listener\Subscriber;
-
-class SendEmailOnPurchaseOrderCreated implements Subscriber
-{
- private $mailer;
-
- public function __construct(\Swift_Mailer $mailer)
- {
- $this->mailer = $mailer;
- }
-
- public static function subscribedEvents(): array
+ public static function getSubscribedEvents(): array
{
return [
- PurchaseOrderCreatedEvent::class => ['onPurchaseOrderCreated'],
+ PurchaseOrderCreatedEvent::class => 'onPurchaseOrderCreated',
];
}
@@ -240,8 +89,8 @@ class SendEmailOnPurchaseOrderCreated implements Subscriber
->setTo('recipient@example.com')
->setBody(sprintf(
'Purchase order created at %s for customer #%s',
- $event->createAt()->format('Y-m-d'),
- $event->customerId()
+ $event->create_at->format('Y-m-d'),
+ $event->customer_id,
));
$this->mailer->send($message);
@@ -249,193 +98,16 @@ class SendEmailOnPurchaseOrderCreated implements Subscriber
}
```
-Register event subscriber
-
-```yml
-services:
- SendEmailOnPurchaseOrderCreated:
- arguments: [ '@mailer' ]
- tags:
- - { name: domain_event.subscriber }
-```
-
-Use pull Predis queue
----------------------
-
-Install [Predis](https://github.com/nrk/predis) with [Composer](http://packagist.org), run:
-
-```sh
-composer require predis/predis
-```
-
-Register services:
-
-```yml
-services:
- # Predis
- Predis\Client:
- arguments: [ '127.0.0.1' ]
-
- # Events serializer for queue
- GpsLab\Domain\Event\Queue\Serializer\SymfonySerializer:
- arguments: [ '@serializer', 'json' ]
-
- # Predis event queue
- GpsLab\Domain\Event\Queue\Pull\PredisPullEventQueue:
- arguments:
- - '@Predis\Client'
- - '@GpsLab\Domain\Event\Queue\Serializer\SymfonySerializer'
- - '@logger'
- - 'event_queue_name'
-```
-
-Change config for use custom queue:
-
-```yml
-gpslab_domain_event:
- queue: 'GpsLab\Domain\Event\Queue\Pull\PredisPullEventQueue'
-```
-
-And now you can use custom queue:
-
-```php
-use GpsLab\Domain\Event\Queue\EventQueue;
-
-$container->get(EventQueue::class)->publish($domain_event);
-```
-
-In latter pull events from queue:
-
-```php
-use GpsLab\Domain\Event\Queue\EventQueue;
-
-$queue = $container->get(EventQueue::class);
-$bus = $container->get(EventQueue::class);
-
-while ($event = $queue->pull()) {
- $bus->publish($event);
-}
-```
-
-Use Predis subscribe queue
---------------------------
-
-Install [Predis PubSub](https://github.com/Superbalist/php-pubsub-redis) adapter with [Composer](http://packagist.org), run:
-
-```sh
-composer require superbalist/php-pubsub-redis
-```
-
-Register services:
-
-```yml
-services:
- # Predis
- Predis\Client:
- arguments: [ '127.0.0.1' ]
-
- # Predis PubSub adapter
- Superbalist\PubSub\Redis\RedisPubSubAdapter:
- arguments: [ '@Predis\Client' ]
-
- # Events serializer for queue
- GpsLab\Domain\Event\Queue\Serializer\SymfonySerializer:
- arguments: [ '@serializer', 'json' ]
-
- # Predis event queue
- GpsLab\Domain\Event\Queue\Subscribe\PredisSubscribeEventQueue:
- arguments:
- - '@Superbalist\PubSub\Redis\RedisPubSubAdapter'
- - '@GpsLab\Domain\Event\Queue\Serializer\SymfonySerializer'
- - '@logger'
- - 'event_queue_name'
-```
-
-Change config for use custom queue:
-
-```yml
-gpslab_domain_event:
- queue: 'GpsLab\Domain\Event\Queue\Subscribe\PredisSubscribeEventQueue'
-```
-
-And now you can use custom queue:
+Publish events
```php
-use GpsLab\Domain\Event\Queue\EventQueue;
-
-$container->get(EventQueue::class)->publish($domain_event);
-```
-
-Subscribe on the queue:
-
-```php
-use GpsLab\Domain\Event\Queue\EventQueue;
-
-$container->get(EventQueue::class)->subscribe(function (Event $event) {
- // do somthing
-});
-```
-
-> **Note**
->
-> You can use subscribe handlers as a services and [tag](http://symfony.com/doc/current/service_container/tags.html) it
-for optimize register.
-
-Many queues
------------
-
-You can use many queues for separation the flows. For example, you want to handle events of different Bounded Contexts
-separately from each other.
-
-```yml
-services:
- acme.domain.purchase_order.event.queue:
- class: GpsLab\Domain\Event\Queue\Pull\PredisPullEventQueue
- arguments:
- - '@Superbalist\PubSub\Redis\RedisPubSubAdapter'
- - '@GpsLab\Domain\Event\Queue\Serializer\SymfonySerializer'
- - '@logger'
- - 'purchase_order_event_queue'
-
- acme.domain.article_comment.event.queue:
- class: GpsLab\Domain\Event\Queue\Pull\PredisPullEventQueue
- arguments:
- - '@Superbalist\PubSub\Redis\RedisPubSubAdapter'
- - '@GpsLab\Domain\Event\Queue\Serializer\SymfonySerializer'
- - '@logger'
- - 'article_comment_event_queue'
-```
-
-And now you can use a different queues.
-
-In **Purchase order** Bounded Contexts.
-
-```php
-$event = new PurchaseOrderCreatedEvent(
- new CustomerId(1),
- new \DateTimeImmutable()
-);
-
-$container->get('acme.domain.purchase_order.event.queue')->publish($event);
-```
-
-In **Article comment** Bounded Contexts.
-
-```php
-$event = new ArticleCommentedEvent(
- new ArticleId(1),
- new AuthorId(1),
- $comment
- new \DateTimeImmutable()
-);
+// do what you need to do on your Domain
+$purchase_order = new PurchaseOrder(new CustomerId(1));
-$container->get('acme.domain.article_comment.event.queue')->publish($event);
+$em->persist($purchase_order);
+$em->flush();
```
-> **Note**
->
-> Similarly, you can split the subscribe queues.
-
License
-------
diff --git a/composer.json b/composer.json
index 8a97580..3d318fd 100644
--- a/composer.json
+++ b/composer.json
@@ -12,22 +12,26 @@
"autoload-dev": {
"psr-4": {
"GpsLab\\Bundle\\DomainEvent\\Tests\\": "tests/"
- }
+ },
+ "classmap": [
+ "tests/Fixtures/Event/Acme_Demo_PurchaseOrderCreated.php"
+ ]
},
"require": {
- "php": ">=5.5.0",
- "gpslab/domain-event": "~2.0",
- "symfony/http-kernel": "~2.3|~3.0|~4.0|~5.0",
- "symfony/dependency-injection": "~2.3|~3.0|~4.0|~5.0",
- "symfony/expression-language": "~2.3|~3.0|~4.0|~5.0",
+ "php": ">=7.4.0",
+ "symfony/http-kernel": "~4.0|~5.0",
+ "symfony/dependency-injection": "~4.0|~5.0",
+ "symfony/config": "~4.0|~5.0",
+ "symfony/expression-language": "~4.0|~5.0",
+ "symfony/event-dispatcher": "~4.0|~5.0",
"doctrine/orm": "~2.4"
},
"require-dev": {
- "phpunit/phpunit": "^4.8.36"
+ "phpunit/phpunit": "~9.5"
},
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-master": "3.0-dev"
}
}
}
diff --git a/src/DependencyInjection/Compiler/EventListenerPass.php b/src/DependencyInjection/Compiler/EventListenerPass.php
deleted file mode 100644
index 73f95c0..0000000
--- a/src/DependencyInjection/Compiler/EventListenerPass.php
+++ /dev/null
@@ -1,62 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT
- */
-
-namespace GpsLab\Bundle\DomainEvent\DependencyInjection\Compiler;
-
-use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Definition;
-
-class EventListenerPass implements CompilerPassInterface
-{
- /**
- * @param ContainerBuilder $container
- */
- public function process(ContainerBuilder $container)
- {
- if (!$container->has('domain_event.locator')) {
- return;
- }
-
- $current_locator = $container->findDefinition('domain_event.locator');
- $symfony_locator = $container->findDefinition('domain_event.locator.symfony');
- $container_locator = $container->findDefinition('domain_event.locator.container');
-
- if ($current_locator === $symfony_locator || $current_locator === $container_locator) {
- $this->registerListeners($container, $current_locator);
- $this->registerSubscribers($container, $current_locator);
- }
- }
-
- /**
- * @param ContainerBuilder $container
- * @param Definition $current_locator
- */
- private function registerListeners(ContainerBuilder $container, Definition $current_locator)
- {
- foreach ($container->findTaggedServiceIds('domain_event.listener') as $id => $attributes) {
- foreach ($attributes as $attribute) {
- $method = !empty($attribute['method']) ? $attribute['method'] : '__invoke';
- $current_locator->addMethodCall('registerService', [$attribute['event'], $id, $method]);
- }
- }
- }
-
- /**
- * @param ContainerBuilder $container
- * @param Definition $current_locator
- */
- private function registerSubscribers(ContainerBuilder $container, Definition $current_locator)
- {
- foreach ($container->findTaggedServiceIds('domain_event.subscriber') as $id => $attributes) {
- $subscriber = $container->findDefinition($id);
- $current_locator->addMethodCall('registerSubscriberService', [$id, $subscriber->getClass()]);
- }
- }
-}
diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php
deleted file mode 100644
index 0aef668..0000000
--- a/src/DependencyInjection/Configuration.php
+++ /dev/null
@@ -1,90 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT
- */
-
-namespace GpsLab\Bundle\DomainEvent\DependencyInjection;
-
-use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-use Symfony\Component\Config\Definition\ConfigurationInterface;
-
-class Configuration implements ConfigurationInterface
-{
- /**
- * Config tree builder.
- *
- * Example config:
- *
- * gpslab_domain_event:
- * bus: 'listener_located'
- * queue: 'pull_memory'
- * locator: 'symfony'
- *
- * @return TreeBuilder
- */
- public function getConfigTreeBuilder()
- {
- $tree_builder = $this->createTreeBuilder('gpslab_domain_event');
- $root = $this->getRootNode($tree_builder, 'gpslab_domain_event');
-
- $bus = $root->children()->scalarNode('bus');
- $bus->cannotBeEmpty()->defaultValue('listener_located');
-
- $queue = $root->children()->scalarNode('queue');
- $queue->cannotBeEmpty()->defaultValue('pull_memory');
-
- $locator = $root->children()->scalarNode('locator');
- $locator->cannotBeEmpty()->defaultValue('symfony');
-
- $publish_on_flush = $root->children()->booleanNode('publish_on_flush');
- $publish_on_flush->defaultValue(false);
-
- return $tree_builder;
- }
-
- /**
- * @param string $name
- *
- * @return TreeBuilder
- */
- private function createTreeBuilder($name)
- {
- // Symfony 4.2 +
- if (method_exists(TreeBuilder::class, '__construct')) {
- return new TreeBuilder($name);
- }
-
- // Symfony 4.1 and below
- return new TreeBuilder();
- }
-
- /**
- * @param TreeBuilder $tree_builder
- * @param string $name
- *
- * @return ArrayNodeDefinition
- */
- private function getRootNode(TreeBuilder $tree_builder, $name)
- {
- if (method_exists($tree_builder, 'getRootNode')) {
- // Symfony 4.2 +
- $root = $tree_builder->getRootNode();
- } else {
- // Symfony 4.1 and below
- $root = $tree_builder->root($name);
- }
-
- // @codeCoverageIgnoreStart
- if (!($root instanceof ArrayNodeDefinition)) { // should be always false
- throw new \RuntimeException(sprintf('The root node should be instance of %s, got %s instead.', ArrayNodeDefinition::class, get_class($root)));
- }
- // @codeCoverageIgnoreEnd
-
- return $root;
- }
-}
diff --git a/src/DependencyInjection/GpsLabDomainEventExtension.php b/src/DependencyInjection/GpsLabDomainEventExtension.php
index 771760f..4e1f466 100644
--- a/src/DependencyInjection/GpsLabDomainEventExtension.php
+++ b/src/DependencyInjection/GpsLabDomainEventExtension.php
@@ -1,4 +1,5 @@
load('queue.yml');
- $loader->load('bus.yml');
- $loader->load('locator.yml');
- $loader->load('publisher.yml');
-
- $config = $this->processConfiguration(new Configuration(), $configs);
-
- $container->setAlias('domain_event.bus', $this->busRealName($config['bus']));
- $container->setAlias('domain_event.queue', $this->queueRealName($config['queue']));
- $container->setAlias('domain_event.locator', $this->locatorRealName($config['locator']));
- $container->setAlias(EventBus::class, $this->busRealName($config['bus']));
- $container->setAlias(EventQueue::class, $this->queueRealName($config['queue']));
-
- $container->getDefinition('domain_event.publisher')->replaceArgument(2, $config['publish_on_flush']);
-
- // subscribers tagged automatically
- if (method_exists($container, 'registerForAutoconfiguration')) {
- $container
- ->registerForAutoconfiguration(Subscriber::class)
- ->addTag('domain_event.subscriber')
- ->setAutowired(true)
- ;
- }
- }
-
- /**
- * @param string $name
- *
- * @return string
- */
- private function busRealName($name)
- {
- if (in_array($name, ['listener_located', 'queue'])) {
- return 'domain_event.bus.'.$name;
- }
-
- return $name;
- }
-
- /**
- * @param string $name
- *
- * @return string
- */
- private function queueRealName($name)
- {
- if (in_array($name, ['pull_memory', 'subscribe_executing'])) {
- return 'domain_event.queue.'.$name;
- }
-
- return $name;
- }
-
- /**
- * @param string $name
- *
- * @return string
- */
- private function locatorRealName($name)
- {
- if (in_array($name, ['direct_binding', 'container', 'symfony'])) {
- return 'domain_event.locator.'.$name;
- }
-
- return $name;
+ $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
+ $loader->load('services.xml');
}
- /**
- * @return string
- */
- public function getAlias()
+ public function getAlias(): string
{
return 'gpslab_domain_event';
}
diff --git a/src/Event/Aggregator/AbstractAggregateEvents.php b/src/Event/Aggregator/AbstractAggregateEvents.php
new file mode 100644
index 0000000..abb84d8
--- /dev/null
+++ b/src/Event/Aggregator/AbstractAggregateEvents.php
@@ -0,0 +1,16 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Event\Aggregator;
+
+abstract class AbstractAggregateEvents implements AggregateEvents
+{
+ use AggregateEventsTrait;
+}
diff --git a/src/Event/Aggregator/AbstractAggregateEventsRaiseInSelf.php b/src/Event/Aggregator/AbstractAggregateEventsRaiseInSelf.php
new file mode 100644
index 0000000..db1927e
--- /dev/null
+++ b/src/Event/Aggregator/AbstractAggregateEventsRaiseInSelf.php
@@ -0,0 +1,16 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Event\Aggregator;
+
+abstract class AbstractAggregateEventsRaiseInSelf implements AggregateEvents
+{
+ use AggregateEventsRaiseInSelfTrait;
+}
diff --git a/src/Event/Aggregator/AggregateEvents.php b/src/Event/Aggregator/AggregateEvents.php
new file mode 100644
index 0000000..c4672b9
--- /dev/null
+++ b/src/Event/Aggregator/AggregateEvents.php
@@ -0,0 +1,21 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Event\Aggregator;
+
+use Symfony\Contracts\EventDispatcher\Event;
+
+interface AggregateEvents
+{
+ /**
+ * @return Event[]
+ */
+ public function pullEvents(): array;
+}
diff --git a/src/Event/Aggregator/AggregateEventsRaiseInSelfTrait.php b/src/Event/Aggregator/AggregateEventsRaiseInSelfTrait.php
new file mode 100644
index 0000000..98adeb3
--- /dev/null
+++ b/src/Event/Aggregator/AggregateEventsRaiseInSelfTrait.php
@@ -0,0 +1,67 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Event\Aggregator;
+
+use Symfony\Contracts\EventDispatcher\Event;
+
+trait AggregateEventsRaiseInSelfTrait
+{
+ /**
+ * @var Event[]
+ */
+ private array $events = [];
+
+ private function raiseInSelf(Event $event): void
+ {
+ $method = $this->eventHandlerName($event);
+
+ // if method is not exists is not a critical error
+ if (method_exists($this, $method)) {
+ $this->{$method}($event);
+ }
+ }
+
+ protected function raise(Event $event): void
+ {
+ $this->events[] = $event;
+ $this->raiseInSelf($event);
+ }
+
+ /**
+ * @return Event[]
+ */
+ public function pullEvents(): array
+ {
+ $events = $this->events;
+ $this->events = [];
+
+ return $events;
+ }
+
+ /**
+ * Get handler method name from event.
+ *
+ * Override this method if you want to change algorithm to generate the handler method name.
+ */
+ protected function eventHandlerName(Event $event): string
+ {
+ $class = get_class($event);
+
+ if ('Event' === substr($class, -5)) {
+ $class = substr($class, 0, -5);
+ }
+
+ $class = str_replace('_', '\\', $class); // convert names for classes not in namespace
+ $parts = explode('\\', $class);
+
+ return 'on'.end($parts);
+ }
+}
diff --git a/src/Event/Aggregator/AggregateEventsTrait.php b/src/Event/Aggregator/AggregateEventsTrait.php
new file mode 100644
index 0000000..26063c6
--- /dev/null
+++ b/src/Event/Aggregator/AggregateEventsTrait.php
@@ -0,0 +1,37 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Event\Aggregator;
+
+use Symfony\Contracts\EventDispatcher\Event;
+
+trait AggregateEventsTrait
+{
+ /**
+ * @var Event[]
+ */
+ private array $events = [];
+
+ protected function raise(Event $event): void
+ {
+ $this->events[] = $event;
+ }
+
+ /**
+ * @return Event[]
+ */
+ public function pullEvents(): array
+ {
+ $events = $this->events;
+ $this->events = [];
+
+ return $events;
+ }
+}
diff --git a/src/Event/Listener/DomainEventPublisher.php b/src/Event/Listener/DomainEventPublisher.php
deleted file mode 100644
index 423e04d..0000000
--- a/src/Event/Listener/DomainEventPublisher.php
+++ /dev/null
@@ -1,100 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT
- */
-
-namespace GpsLab\Bundle\DomainEvent\Event\Listener;
-
-use Doctrine\Common\EventSubscriber;
-use Doctrine\ORM\Event\OnFlushEventArgs;
-use Doctrine\ORM\Event\PostFlushEventArgs;
-use Doctrine\ORM\Events;
-use GpsLab\Bundle\DomainEvent\Service\EventPuller;
-use GpsLab\Domain\Event\Bus\EventBus;
-use GpsLab\Domain\Event\Event;
-
-class DomainEventPublisher implements EventSubscriber
-{
- /**
- * @var EventPuller
- */
- private $puller;
-
- /**
- * @var EventBus
- */
- private $bus;
-
- /**
- * @var bool
- */
- private $enable;
-
- /**
- * @var Event[]
- */
- private $events = [];
-
- /**
- * @param EventPuller $puller
- * @param EventBus $bus
- * @param bool $enable
- */
- public function __construct(EventPuller $puller, EventBus $bus, $enable)
- {
- $this->bus = $bus;
- $this->puller = $puller;
- $this->enable = $enable;
- }
-
- /**
- * @return array
- */
- public function getSubscribedEvents()
- {
- if (!$this->enable) {
- return [];
- }
-
- return [
- Events::onFlush,
- Events::postFlush,
- ];
- }
-
- /**
- * @param OnFlushEventArgs $args
- */
- public function onFlush(OnFlushEventArgs $args)
- {
- // aggregate events from deleted entities
- $this->events = $this->puller->pull($args->getEntityManager()->getUnitOfWork());
- }
-
- /**
- * @param PostFlushEventArgs $args
- */
- public function postFlush(PostFlushEventArgs $args)
- {
- // aggregate PreRemove/PostRemove events
- $events = array_merge($this->events, $this->puller->pull($args->getEntityManager()->getUnitOfWork()));
-
- // clear aggregate events before publish it
- // it necessary for fix recursive publish of events
- $this->events = [];
-
- // flush only if has domain events
- // it necessary for fix recursive handle flush
- if (!empty($events)) {
- foreach ($events as $event) {
- $this->bus->publish($event);
- }
-
- $args->getEntityManager()->flush();
- }
- }
-}
diff --git a/src/Event/Publisher.php b/src/Event/Publisher.php
new file mode 100644
index 0000000..c320b0f
--- /dev/null
+++ b/src/Event/Publisher.php
@@ -0,0 +1,63 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Event;
+
+use Doctrine\ORM\EntityManagerInterface;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Contracts\EventDispatcher\Event;
+
+class Publisher
+{
+ private Puller $puller;
+ private EventDispatcher $dispatcher;
+
+ /**
+ * @var Event[][]
+ */
+ private array $events = [];
+
+ public function __construct(Puller $puller, EventDispatcher $dispatcher)
+ {
+ $this->dispatcher = $dispatcher;
+ $this->puller = $puller;
+ }
+
+ public function aggregateEvents(EntityManagerInterface $em): void
+ {
+ $emid = spl_object_id($em);
+
+ $this->events[$emid] = array_merge($this->events[$emid] ?? [], $this->puller->pull($em->getUnitOfWork()));
+ }
+
+ public function dispatchEvents(EntityManagerInterface $em): void
+ {
+ $emid = spl_object_id($em);
+
+ if (!isset($this->events[$emid])) {
+ return; // no events for dispatch
+ }
+
+ // clear aggregate events before publish it
+ // it necessary for fix recursive publish of events
+ $events = $this->events[$emid];
+ unset($this->events[$emid]);
+
+ // flush only if has domain events
+ // it necessary for fix recursive handle flush
+ if ($events !== []) {
+ foreach ($events as $event) {
+ $this->dispatcher->dispatch($event);
+ }
+
+ $em->flush();
+ }
+ }
+}
diff --git a/src/Service/EventPuller.php b/src/Event/Puller.php
similarity index 54%
rename from src/Service/EventPuller.php
rename to src/Event/Puller.php
index 657b855..0e72cfc 100644
--- a/src/Service/EventPuller.php
+++ b/src/Event/Puller.php
@@ -1,4 +1,5 @@
pullFromEntities($uow->getScheduledEntityDeletions()));
- $events = array_merge($events, $this->pullFromEntities($uow->getScheduledEntityInsertions()));
- $events = array_merge($events, $this->pullFromEntities($uow->getScheduledEntityUpdates()));
+ $events[] = $this->pullFromEntities($uow->getScheduledEntityDeletions());
+ $events[] = $this->pullFromEntities($uow->getScheduledEntityInsertions());
+ $events[] = $this->pullFromEntities($uow->getScheduledEntityUpdates());
// other entities
foreach ($uow->getIdentityMap() as $entities) {
- $events = array_merge($events, $this->pullFromEntities($entities));
+ $events[] = $this->pullFromEntities($entities);
}
- return $events;
+ return array_merge([], ...$events);
}
/**
- * @param array $entities
+ * @param object[] $entities
*
* @return Event[]
*/
- private function pullFromEntities(array $entities)
+ private function pullFromEntities(array $entities): array
{
$events = [];
@@ -58,10 +57,10 @@ private function pullFromEntities(array $entities)
}
if ($entity instanceof AggregateEvents) {
- $events = array_merge($events, $entity->pullEvents());
+ $events[] = $entity->pullEvents();
}
}
- return $events;
+ return array_merge([], ...$events);
}
}
diff --git a/src/Event/Subscriber/DoctrineEventSubscriber.php b/src/Event/Subscriber/DoctrineEventSubscriber.php
new file mode 100644
index 0000000..a3fa85d
--- /dev/null
+++ b/src/Event/Subscriber/DoctrineEventSubscriber.php
@@ -0,0 +1,52 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Event\Subscriber;
+
+use Doctrine\Common\EventSubscriber;
+use Doctrine\ORM\Event\OnFlushEventArgs;
+use Doctrine\ORM\Event\PostFlushEventArgs;
+use Doctrine\ORM\Events;
+use GpsLab\Bundle\DomainEvent\Event\Publisher;
+
+class DoctrineEventSubscriber implements EventSubscriber
+{
+ private Publisher $publisher;
+
+ public function __construct(Publisher $publisher)
+ {
+ $this->publisher = $publisher;
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getSubscribedEvents(): array
+ {
+ return [
+ Events::onFlush,
+ Events::postFlush,
+ ];
+ }
+
+ public function onFlush(OnFlushEventArgs $args): void
+ {
+ // aggregate events from deleted entities
+ $this->publisher->aggregateEvents($args->getEntityManager());
+ }
+
+ public function postFlush(PostFlushEventArgs $args): void
+ {
+ // aggregate PreRemove/PostRemove events
+ $this->publisher->aggregateEvents($args->getEntityManager());
+
+ $this->publisher->dispatchEvents($args->getEntityManager());
+ }
+}
diff --git a/src/GpsLabDomainEventBundle.php b/src/GpsLabDomainEventBundle.php
index 58bc983..6d386ac 100644
--- a/src/GpsLabDomainEventBundle.php
+++ b/src/GpsLabDomainEventBundle.php
@@ -1,4 +1,5 @@
addCompilerPass(new EventListenerPass());
- }
-
- /**
- * @return GpsLabDomainEventExtension
- */
- public function getContainerExtension()
- {
- if (!($this->extension instanceof GpsLabDomainEventExtension)) {
+ if (!$this->extension instanceof GpsLabDomainEventExtension) {
$this->extension = new GpsLabDomainEventExtension();
}
diff --git a/src/Resources/config/bus.yml b/src/Resources/config/bus.yml
deleted file mode 100644
index 75cf381..0000000
--- a/src/Resources/config/bus.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-services:
- domain_event.bus.listener_located:
- class: GpsLab\Domain\Event\Bus\ListenerLocatedEventBus
- arguments: [ '@domain_event.locator' ]
- public: false
-
- domain_event.bus.queue:
- class: GpsLab\Domain\Event\Bus\QueueEventBus
- arguments: [ '@domain_event.queue' ]
- public: false
diff --git a/src/Resources/config/locator.yml b/src/Resources/config/locator.yml
deleted file mode 100644
index cebec6d..0000000
--- a/src/Resources/config/locator.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-services:
- domain_event.locator.symfony:
- class: GpsLab\Domain\Event\Listener\Locator\SymfonyContainerEventListenerLocator
- calls:
- - [ setContainer, [ '@service_container' ] ]
- public: false
-
- domain_event.locator.container:
- class: GpsLab\Domain\Event\Listener\Locator\ContainerEventListenerLocator
- arguments: [ '@service_container' ]
- public: false
-
- domain_event.locator.direct_binding:
- class: GpsLab\Domain\Event\Listener\Locator\DirectBindingEventListenerLocator
- public: false
diff --git a/src/Resources/config/publisher.yml b/src/Resources/config/publisher.yml
deleted file mode 100644
index d2c524e..0000000
--- a/src/Resources/config/publisher.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-services:
- domain_event.publisher:
- class: GpsLab\Bundle\DomainEvent\Event\Listener\DomainEventPublisher
- arguments: [ '@domain_event.puller', '@domain_event.bus', ~ ]
- tags:
- - { name: doctrine.event_subscriber }
-
- domain_event.puller:
- class: GpsLab\Bundle\DomainEvent\Service\EventPuller
- public: false
diff --git a/src/Resources/config/queue.yml b/src/Resources/config/queue.yml
deleted file mode 100644
index cedb3b7..0000000
--- a/src/Resources/config/queue.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-services:
- domain_event.queue.pull_memory:
- class: GpsLab\Domain\Event\Queue\Pull\MemoryPullEventQueue
- public: false
-
- domain_event.queue.subscribe_executing:
- class: GpsLab\Domain\Event\Queue\Subscribe\ExecutingSubscribeEventQueue
- public: false
diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml
new file mode 100644
index 0000000..5db2d1f
--- /dev/null
+++ b/src/Resources/config/services.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/DependencyInjection/Compiler/EventListenerPassTest.php b/tests/DependencyInjection/Compiler/EventListenerPassTest.php
deleted file mode 100644
index ca77a41..0000000
--- a/tests/DependencyInjection/Compiler/EventListenerPassTest.php
+++ /dev/null
@@ -1,235 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT
- */
-
-namespace GpsLab\Bundle\DomainEvent\Tests\DependencyInjection\Compiler;
-
-use GpsLab\Bundle\DomainEvent\DependencyInjection\Compiler\EventListenerPass;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Definition;
-
-class EventListenerPassTest extends TestCase
-{
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject|ContainerBuilder
- */
- private $container;
-
- /**
- * @var EventListenerPass
- */
- private $pass;
-
- protected function setUp()
- {
- if (PHP_VERSION_ID >= 70000) {
- $this->markTestSkipped(sprintf('Impossible to mock "%s" on PHP 7', ContainerBuilder::class));
- }
-
- $this->container = $this
- ->getMockBuilder(ContainerBuilder::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $this->pass = new EventListenerPass();
- }
-
- public function testProcessNoLocator()
- {
- $this->container
- ->expects($this->once())
- ->method('has')
- ->with('domain_event.locator')
- ->will($this->returnValue(false))
- ;
- $this->container
- ->expects($this->never())
- ->method('findDefinition')
- ;
- $this->container
- ->expects($this->never())
- ->method('findTaggedServiceIds')
- ;
-
- $this->pass->process($this->container);
- }
-
- public function testProcessCustomLocator()
- {
- // create fake definitions to distinguish them
- $symfony_locator = new Definition(null, ['symfony']);
- $container_locator = new Definition(null, ['container']);
- $current_locator = new Definition(null, ['custom']);
-
- $this->container
- ->expects($this->at(0))
- ->method('has')
- ->with('domain_event.locator')
- ->will($this->returnValue(true))
- ;
- $this->container
- ->expects($this->at(1))
- ->method('findDefinition')
- ->with('domain_event.locator')
- ->will($this->returnValue($current_locator))
- ;
- $this->container
- ->expects($this->at(2))
- ->method('findDefinition')
- ->with('domain_event.locator.symfony')
- ->will($this->returnValue($symfony_locator))
- ;
- $this->container
- ->expects($this->at(3))
- ->method('findDefinition')
- ->with('domain_event.locator.container')
- ->will($this->returnValue($container_locator))
- ;
- $this->container
- ->expects($this->never())
- ->method('findTaggedServiceIds')
- ;
-
- $this->pass->process($this->container);
- }
-
- /**
- * @return array
- */
- public function locators()
- {
- if (PHP_VERSION_ID >= 70000) {
- $this->markTestSkipped(sprintf('Impossible to mock "%s" on PHP 7', Definition::class));
- }
-
- $locator = $this->getMock(Definition::class);
-
- return [
- [
- $locator,
- new Definition(),
- $locator,
- ],
- [
- new Definition(),
- $locator,
- $locator,
- ],
- ];
- }
-
- /**
- * @dataProvider locators
- *
- * @param \PHPUnit_Framework_MockObject_MockObject|Definition $symfony_locator
- * @param \PHPUnit_Framework_MockObject_MockObject|Definition $container_locator
- * @param \PHPUnit_Framework_MockObject_MockObject|Definition $current_locator
- */
- public function testProcess(
- Definition $symfony_locator,
- Definition $container_locator,
- Definition $current_locator
- ) {
- $listeners = [
- 'foo' => [
- ['event' => 'PurchaseOrderCompletedEvent', 'method' => 'onPurchaseOrderCompleted'],
- ['event' => 'PurchaseOrderCreated', 'method' => 'onPurchaseOrderCreated'],
- ],
- 'bar' => [
- ['event' => 'PurchaseOrderCompletedEvent'],
- ],
- 'baz' => [
- ['event' => 'PurchaseOrderCreated', 'method' => 'handle'],
- ],
- ];
- $subscribers = [
- 'foo' => [],
- 'bar' => [],
- 'baz' => [],
- ];
-
- $locator_index = 0;
- $container_index = 0;
-
- $this->container
- ->expects($this->at($container_index++))
- ->method('has')
- ->with('domain_event.locator')
- ->will($this->returnValue(true))
- ;
- $this->container
- ->expects($this->at($container_index++))
- ->method('findDefinition')
- ->with('domain_event.locator')
- ->will($this->returnValue($current_locator))
- ;
- $this->container
- ->expects($this->at($container_index++))
- ->method('findDefinition')
- ->with('domain_event.locator.symfony')
- ->will($this->returnValue($symfony_locator))
- ;
- $this->container
- ->expects($this->at($container_index++))
- ->method('findDefinition')
- ->with('domain_event.locator.container')
- ->will($this->returnValue($container_locator))
- ;
- $this->container
- ->expects($this->at($container_index++))
- ->method('findTaggedServiceIds')
- ->with('domain_event.listener')
- ->will($this->returnValue($listeners))
- ;
- $this->container
- ->expects($this->at($container_index++))
- ->method('findTaggedServiceIds')
- ->with('domain_event.subscriber')
- ->will($this->returnValue($subscribers))
- ;
-
- foreach ($listeners as $id => $attributes) {
- foreach ($attributes as $attribute) {
- $method = !empty($attribute['method']) ? $attribute['method'] : '__invoke';
-
- $current_locator
- ->expects($this->at($locator_index++))
- ->method('addMethodCall')
- ->with('registerService', [$attribute['event'], $id, $method])
- ;
- }
- }
-
- foreach ($subscribers as $id => $attributes) {
- $class_name = $id;
-
- $subscriber = $this->getMock(Definition::class);
- $subscriber
- ->expects($this->once())
- ->method('getClass')
- ->will($this->returnValue($class_name))
- ;
-
- $this->container
- ->expects($this->at($container_index++))
- ->method('findDefinition')
- ->with($id)
- ->will($this->returnValue($subscriber))
- ;
-
- $current_locator
- ->expects($this->at($locator_index++))
- ->method('addMethodCall')
- ->with('registerSubscriberService', [$id, $class_name])
- ;
- }
-
- $this->pass->process($this->container);
- }
-}
diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php
deleted file mode 100644
index 524a7f8..0000000
--- a/tests/DependencyInjection/ConfigurationTest.php
+++ /dev/null
@@ -1,60 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT
- */
-
-namespace GpsLab\Bundle\DomainEvent\Tests\DependencyInjection;
-
-use GpsLab\Bundle\DomainEvent\DependencyInjection\Configuration;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\ArrayNode;
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-use Symfony\Component\Config\Definition\ScalarNode;
-
-class ConfigurationTest extends TestCase
-{
- /**
- * @var Configuration
- */
- private $configuration;
-
- protected function setUp()
- {
- $this->configuration = new Configuration();
- }
-
- public function testConfigTree()
- {
- $tree_builder = $this->configuration->getConfigTreeBuilder();
-
- $this->assertInstanceOf(TreeBuilder::class, $tree_builder);
-
- /* @var $tree ArrayNode */
- $tree = $tree_builder->buildTree();
-
- $this->assertInstanceOf(ArrayNode::class, $tree);
- $this->assertEquals('gpslab_domain_event', $tree->getName());
-
- /* @var $children ScalarNode[] */
- $children = $tree->getChildren();
-
- $this->assertInternalType('array', $children);
- $this->assertEquals(['bus', 'queue', 'locator', 'publish_on_flush'], array_keys($children));
-
- $this->assertInstanceOf(ScalarNode::class, $children['bus']);
- $this->assertEquals('listener_located', $children['bus']->getDefaultValue());
- $this->assertFalse($children['bus']->isRequired());
-
- $this->assertInstanceOf(ScalarNode::class, $children['queue']);
- $this->assertEquals('pull_memory', $children['queue']->getDefaultValue());
- $this->assertFalse($children['queue']->isRequired());
-
- $this->assertInstanceOf(ScalarNode::class, $children['locator']);
- $this->assertEquals('symfony', $children['locator']->getDefaultValue());
- $this->assertFalse($children['locator']->isRequired());
- }
-}
diff --git a/tests/DependencyInjection/GpsLabDomainEventExtensionTest.php b/tests/DependencyInjection/GpsLabDomainEventExtensionTest.php
index f13cfc8..5b9cf84 100644
--- a/tests/DependencyInjection/GpsLabDomainEventExtensionTest.php
+++ b/tests/DependencyInjection/GpsLabDomainEventExtensionTest.php
@@ -1,4 +1,5 @@
extension = new GpsLabDomainEventExtension();
$this->container = new ContainerBuilder();
}
- /**
- * @return array
- */
- public function config()
+ public function testLoad(): void
{
- return [
- [
- [],
- 'domain_event.bus.listener_located',
- 'domain_event.queue.pull_memory',
- 'domain_event.locator.symfony',
- false,
- ],
- [
- [
- 'gpslab_domain_event' => [
- 'bus' => 'queue',
- 'queue' => 'subscribe_executing',
- 'locator' => 'container',
- 'publish_on_flush' => false,
- ],
- ],
- 'domain_event.bus.queue',
- 'domain_event.queue.subscribe_executing',
- 'domain_event.locator.container',
- false,
- ],
- [
- [
- 'gpslab_domain_event' => [
- 'bus' => 'queue',
- 'queue' => 'subscribe_executing',
- 'locator' => 'direct_binding',
- 'publish_on_flush' => true,
- ],
- ],
- 'domain_event.bus.queue',
- 'domain_event.queue.subscribe_executing',
- 'domain_event.locator.direct_binding',
- true,
- ],
- [
- [
- 'gpslab_domain_event' => [
- 'bus' => 'acme.domain.event.bus',
- 'queue' => 'acme.domain.event.queue',
- 'locator' => 'acme.domain.event.locator',
- 'publish_on_flush' => true,
- ],
- ],
- 'acme.domain.event.bus',
- 'acme.domain.event.queue',
- 'acme.domain.event.locator',
- true,
- ],
- ];
- }
-
- /**
- * @dataProvider config
- *
- * @param array $config
- * @param string $bus
- * @param string $queue
- * @param string $locator
- * @param bool $publish_on_flush
- */
- public function testLoad(array $config, $bus, $queue, $locator, $publish_on_flush)
- {
- $this->extension->load($config, $this->container);
-
- $this->assertEquals($bus, $this->container->getAlias('domain_event.bus'));
- $this->assertEquals($queue, $this->container->getAlias('domain_event.queue'));
- $this->assertEquals($locator, $this->container->getAlias('domain_event.locator'));
- $this->assertEquals($bus, $this->container->getAlias(EventBus::class));
- $this->assertEquals($queue, $this->container->getAlias(EventQueue::class));
-
- $publisher = $this->container->getDefinition('domain_event.publisher');
- $this->assertEquals($publish_on_flush, $publisher->getArgument(2));
+ $this->extension->load([], $this->container);
- if (method_exists($this->container, 'registerForAutoconfiguration')) {
- $has_subscriber = false;
- foreach ($this->container->getAutoconfiguredInstanceof() as $key => $definition) {
- if ($key === Subscriber::class) {
- $has_subscriber = true;
- $this->assertTrue($definition->hasTag('domain_event.subscriber'));
- $this->assertTrue($definition->isAutowired());
- }
- }
- $this->assertTrue($has_subscriber);
- }
+ $this->assertTrue($this->container->hasDefinition(Puller::class));
+ $this->assertTrue($this->container->hasDefinition(Publisher::class));
+ $this->assertTrue($this->container->hasDefinition(DoctrineEventSubscriber::class));
}
- public function testAlias()
+ public function testAlias(): void
{
$this->assertEquals('gpslab_domain_event', $this->extension->getAlias());
}
diff --git a/tests/Event/Aggregator/AggregateEventsRaiseInSelfTest.php b/tests/Event/Aggregator/AggregateEventsRaiseInSelfTest.php
new file mode 100644
index 0000000..9d71484
--- /dev/null
+++ b/tests/Event/Aggregator/AggregateEventsRaiseInSelfTest.php
@@ -0,0 +1,61 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Tests\Event\Aggregator;
+
+use GpsLab\Bundle\DomainEvent\Tests\Fixtures\DemoAggregatorRaiseInSelf;
+use GpsLab\Bundle\DomainEvent\Tests\Fixtures\Event\PurchaseOrderCreatedEvent;
+use PHPUnit\Framework\TestCase;
+use Symfony\Contracts\EventDispatcher\Event;
+
+class AggregateEventsRaiseInSelfTest extends TestCase
+{
+ private DemoAggregatorRaiseInSelf $aggregator;
+
+ protected function setUp(): void
+ {
+ $this->aggregator = new DemoAggregatorRaiseInSelf();
+ }
+
+ public function testRaiseAndPullEvents()
+ {
+ $this->assertEquals([], $this->aggregator->pullEvents());
+
+ $events = [
+ new Event(),
+ new Event(),
+ ];
+
+ foreach ($events as $event) {
+ $this->aggregator->raiseEvent($event);
+ $this->assertNull($this->aggregator->getRaiseInSelfEvent());
+ }
+
+ $this->assertEquals($events, $this->aggregator->pullEvents());
+ $this->assertEquals([], $this->aggregator->pullEvents());
+ }
+
+ public function testRaiseInSel(): void
+ {
+ $this->assertEquals([], $this->aggregator->pullEvents());
+
+ $event1 = new PurchaseOrderCreatedEvent();
+ $event2 = new \Acme_Demo_PurchaseOrderCreated();
+
+ $this->aggregator->raiseEvent($event1);
+ $this->assertEquals($event1, $this->aggregator->getRaiseInSelfEvent());
+
+ $this->aggregator->raiseEvent($event2);
+ $this->assertEquals($event2, $this->aggregator->getRaiseInSelfEvent());
+
+ $this->assertEquals([$event1, $event2], $this->aggregator->pullEvents());
+ $this->assertEquals([], $this->aggregator->pullEvents());
+ }
+}
diff --git a/tests/Event/Aggregator/AggregateEventsTest.php b/tests/Event/Aggregator/AggregateEventsTest.php
new file mode 100644
index 0000000..97fe800
--- /dev/null
+++ b/tests/Event/Aggregator/AggregateEventsTest.php
@@ -0,0 +1,42 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Tests\Event\Aggregator;
+
+use GpsLab\Bundle\DomainEvent\Tests\Fixtures\DemoAggregator;
+use PHPUnit\Framework\TestCase;
+use Symfony\Contracts\EventDispatcher\Event;
+
+class AggregateEventsTest extends TestCase
+{
+ private DemoAggregator $aggregator;
+
+ protected function setUp(): void
+ {
+ $this->aggregator = new DemoAggregator();
+ }
+
+ public function testRaiseAndPullEvents(): void
+ {
+ $this->assertEquals([], $this->aggregator->pullEvents());
+
+ $events = [
+ new Event(),
+ new Event(),
+ ];
+
+ foreach ($events as $event) {
+ $this->aggregator->raiseEvent($event);
+ }
+
+ $this->assertEquals($events, $this->aggregator->pullEvents());
+ $this->assertEquals([], $this->aggregator->pullEvents());
+ }
+}
diff --git a/tests/Event/Listener/DomainEventPublisherTest.php b/tests/Event/Listener/DomainEventPublisherTest.php
deleted file mode 100644
index 3b32612..0000000
--- a/tests/Event/Listener/DomainEventPublisherTest.php
+++ /dev/null
@@ -1,277 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT
- */
-
-namespace GpsLab\Bundle\DomainEvent\Tests\Event\Listener;
-
-use Doctrine\ORM\EntityManagerInterface;
-use Doctrine\ORM\Event\OnFlushEventArgs;
-use Doctrine\ORM\Event\PostFlushEventArgs;
-use Doctrine\ORM\Events;
-use Doctrine\ORM\UnitOfWork;
-use GpsLab\Bundle\DomainEvent\Event\Listener\DomainEventPublisher;
-use GpsLab\Bundle\DomainEvent\Service\EventPuller;
-use GpsLab\Domain\Event\Bus\EventBus;
-use GpsLab\Domain\Event\Event;
-use PHPUnit\Framework\TestCase;
-
-class DomainEventPublisherTest extends TestCase
-{
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject|EventBus
- */
- private $bus;
-
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject|EventPuller
- */
- private $puller;
-
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject|EntityManagerInterface
- */
- private $em;
-
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject|UnitOfWork
- */
- private $uow;
-
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject|OnFlushEventArgs
- */
- private $on_flush;
-
- /**
- * @var \PHPUnit_Framework_MockObject_MockObject|PostFlushEventArgs
- */
- private $post_flush;
-
- /**
- * @var DomainEventPublisher
- */
- private $publisher;
-
- protected function setUp()
- {
- $this->bus = $this->getMockBuilder(EventBus::class)->getMock();
- $this->puller = $this->getMockBuilder(EventPuller::class)->getMock();
- $this->em = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
-
- $this->on_flush = $this
- ->getMockBuilder(OnFlushEventArgs::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $this->on_flush
- ->expects($this->any())
- ->method('getEntityManager')
- ->will($this->returnValue($this->em))
- ;
-
- $this->post_flush = $this
- ->getMockBuilder(PostFlushEventArgs::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
- $this->post_flush
- ->expects($this->any())
- ->method('getEntityManager')
- ->will($this->returnValue($this->em))
- ;
-
- $this->uow = $this
- ->getMockBuilder(UnitOfWork::class)
- ->disableOriginalConstructor()
- ->getMock()
- ;
-
- $this->publisher = new DomainEventPublisher($this->puller, $this->bus, true);
- }
-
- public function testDisabled()
- {
- $publisher = new DomainEventPublisher($this->puller, $this->bus, false);
- $this->assertEquals([], $publisher->getSubscribedEvents());
- }
-
- public function testEnabled()
- {
- $publisher = new DomainEventPublisher($this->puller, $this->bus, true);
- $this->assertEquals([Events::onFlush, Events::postFlush], $publisher->getSubscribedEvents());
- }
-
- public function testPreFlush()
- {
- $this->em
- ->expects($this->once())
- ->method('getUnitOfWork')
- ->will($this->returnValue($this->uow))
- ;
-
- $this->puller
- ->expects($this->once())
- ->method('pull')
- ->with($this->uow)
- ;
-
- $this->publisher->onFlush($this->on_flush);
- }
-
- /**
- * @return array
- */
- public function events()
- {
- $events1 = [
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- ];
- $events2 = [
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- ];
-
- return [
- [[], [], []],
- [$events1, []],
- [[], $events2],
- [$events1, $events2],
- ];
- }
-
- /**
- * @dataProvider events
- *
- * @param array $remove_events
- * @param array $exist_events
- */
- public function testPublishEvents(array $remove_events, array $exist_events)
- {
- $this->puller
- ->expects($this->at(0))
- ->method('pull')
- ->with($this->uow)
- ->will($this->returnValue($remove_events))
- ;
- $this->puller
- ->expects($this->at(1))
- ->method('pull')
- ->with($this->uow)
- ->will($this->returnValue($exist_events))
- ;
-
- $expected_events = array_merge($remove_events, $exist_events);
-
- if ($expected_events) {
- foreach ($expected_events as $i => $expected_event) {
- $this->bus
- ->expects($this->at($i))
- ->method('publish')
- ->with($expected_event)
- ;
- }
- $this->em
- ->expects($this->once())
- ->method('flush')
- ;
- } else {
- $this->bus
- ->expects($this->never())
- ->method('publish')
- ;
- $this->em
- ->expects($this->never())
- ->method('flush')
- ;
- }
- $this->em
- ->expects($this->atLeastOnce())
- ->method('getUnitOfWork')
- ->will($this->returnValue($this->uow))
- ;
-
- $this->publisher->onFlush($this->on_flush);
- $this->publisher->postFlush($this->post_flush);
- }
-
- public function testRecursivePublish()
- {
- $remove_events1 = [
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- ];
- $remove_events2 = [
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- ];
- $exist_events1 = [
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- ];
- $exist_events2 = [
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- $this->getMockBuilder(Event::class)->getMock(),
- ];
-
- $this->em
- ->expects($this->atLeastOnce())
- ->method('getUnitOfWork')
- ->will($this->returnValue($this->uow))
- ;
- $this->em
- ->expects($this->exactly(2))
- ->method('flush')
- ;
-
- $this->puller
- ->expects($this->at(0))
- ->method('pull')
- ->with($this->uow)
- ->will($this->returnValue($remove_events1))
- ;
- $this->puller
- ->expects($this->at(1))
- ->method('pull')
- ->with($this->uow)
- ->will($this->returnValue($exist_events1))
- ;
- $this->puller
- ->expects($this->at(2))
- ->method('pull')
- ->with($this->uow)
- ->will($this->returnValue($remove_events2))
- ;
- $this->puller
- ->expects($this->at(3))
- ->method('pull')
- ->with($this->uow)
- ->will($this->returnValue($exist_events2))
- ;
-
- $expected_events = array_merge($remove_events1, $exist_events1, $remove_events2, $exist_events2);
- foreach ($expected_events as $i => $expected_event) {
- $this->bus
- ->expects($this->at($i))
- ->method('publish')
- ->with($expected_event)
- ;
- }
-
- $this->publisher->onFlush($this->on_flush);
- $this->publisher->postFlush($this->post_flush);
- // recursive call
- $this->publisher->onFlush($this->on_flush);
- $this->publisher->postFlush($this->post_flush);
- }
-}
diff --git a/tests/Event/PublisherTest.php b/tests/Event/PublisherTest.php
new file mode 100644
index 0000000..288272f
--- /dev/null
+++ b/tests/Event/PublisherTest.php
@@ -0,0 +1,197 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Tests\Event;
+
+use Doctrine\ORM\EntityManagerInterface;
+use Doctrine\ORM\UnitOfWork;
+use GpsLab\Bundle\DomainEvent\Event\Publisher;
+use GpsLab\Bundle\DomainEvent\Event\Puller;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Contracts\EventDispatcher\Event;
+
+class PublisherTest extends TestCase
+{
+ /**
+ * @var MockObject&EventDispatcherInterface
+ */
+ private EventDispatcherInterface $dispatcher;
+
+ /**
+ * @var MockObject&Puller
+ */
+ private Puller $puller;
+
+ /**
+ * @var MockObject&EntityManagerInterface
+ */
+ private EntityManagerInterface $em;
+
+ /**
+ * @var MockObject&UnitOfWork
+ */
+ private UnitOfWork $uow;
+
+ private Publisher $publisher;
+
+ protected function setUp(): void
+ {
+ $this->dispatcher = $this->getMockBuilder(EventDispatcher::class)->getMock();
+ $this->puller = $this->getMockBuilder(Puller::class)->getMock();
+ $this->em = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
+ $this->uow = $this
+ ->getMockBuilder(UnitOfWork::class)
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+
+ $this->publisher = new Publisher($this->puller, $this->dispatcher);
+ }
+
+ public function testNothingDispatch(): void
+ {
+ $this->dispatcher
+ ->expects($this->never())
+ ->method('dispatch')
+ ;
+ $this->em
+ ->expects($this->never())
+ ->method('flush')
+ ;
+
+ $this->publisher->dispatchEvents($this->em);
+ }
+
+ public function testDispatchEvents(): void
+ {
+ $this->em
+ ->expects($this->once())
+ ->method('getUnitOfWork')
+ ->willReturn($this->uow)
+ ;
+
+ $events = [
+ new Event(),
+ new Event(),
+ new Event(),
+ ];
+ $arguments = [];
+
+ foreach ($events as $event) {
+ $arguments[] = [$event];
+ }
+
+ $this->puller
+ ->expects($this->once())
+ ->method('pull')
+ ->with($this->uow)
+ ->willReturn($events)
+ ;
+
+ $this->dispatcher
+ ->expects($this->atLeastOnce())
+ ->method('dispatch')
+ ->withConsecutive(...$arguments)
+ ;
+
+ $this->em
+ ->expects($this->once())
+ ->method('flush')
+ ;
+
+ $this->publisher->aggregateEvents($this->em);
+ $this->publisher->dispatchEvents($this->em);
+ }
+
+ /**
+ * @return Event[][][]
+ */
+ public function provideEvents(): array
+ {
+ return [
+ [
+ [
+ new Event(),
+ new Event(),
+ new Event(),
+ ],
+ [],
+ ],
+ [
+ [],
+ [
+ new Event(),
+ new Event(),
+ new Event(),
+ ],
+ ],
+ [
+ [
+ new Event(),
+ new Event(),
+ new Event(),
+ ],
+ [
+ new Event(),
+ new Event(),
+ new Event(),
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider provideEvents
+ *
+ * @param Event[] $first_loop
+ * @param Event[] $second_loop
+ */
+ public function testDispatchEventsRecursive(array $first_loop, array $second_loop): void
+ {
+ $this->em
+ ->expects($this->atLeastOnce())
+ ->method('getUnitOfWork')
+ ->willReturn($this->uow)
+ ;
+
+ $arguments = [];
+
+ foreach (array_merge($first_loop, $second_loop) as $event) {
+ $arguments[] = [$event];
+ }
+
+ $this->puller
+ ->expects($this->atLeastOnce())
+ ->method('pull')
+ ->with($this->uow)
+ ->willReturnOnConsecutiveCalls($first_loop, $second_loop)
+ ;
+
+ $this->dispatcher
+ ->expects($this->atLeastOnce())
+ ->method('dispatch')
+ ->withConsecutive(...$arguments)
+ ;
+
+ $this->em
+ ->expects($first_loop !== [] && $second_loop !== [] ? $this->atLeastOnce() : $this->once())
+ ->method('flush')
+ ;
+
+ $this->publisher->aggregateEvents($this->em);
+ $this->publisher->dispatchEvents($this->em);
+ // recursive call
+ $this->publisher->aggregateEvents($this->em);
+ $this->publisher->dispatchEvents($this->em);
+ }
+}
diff --git a/tests/Service/EventPullerTest.php b/tests/Event/PullerTest.php
similarity index 74%
rename from tests/Service/EventPullerTest.php
rename to tests/Event/PullerTest.php
index 51dfdea..9ba1ee5 100644
--- a/tests/Service/EventPullerTest.php
+++ b/tests/Event/PullerTest.php
@@ -1,4 +1,5 @@
uow = $this
->getMockBuilder(UnitOfWork::class)
@@ -37,13 +36,13 @@ protected function setUp()
->getMock()
;
- $this->puller = new EventPuller();
+ $this->puller = new Puller();
}
/**
- * @return array
+ * @return Event[][][]
*/
- public function events()
+ public function provideEvents(): array
{
$events1 = [
$this->getMockBuilder(Event::class)->getMock(),
@@ -88,31 +87,34 @@ public function events()
}
/**
- * @dataProvider events
+ * @dataProvider provideEvents
*
- * @param \PHPUnit_Framework_MockObject_MockObject[] $deletions_events
- * @param \PHPUnit_Framework_MockObject_MockObject[] $insertions_events
- * @param \PHPUnit_Framework_MockObject_MockObject[] $updates_events
- * @param \PHPUnit_Framework_MockObject_MockObject[] $map_events
+ * @param Event[] $deletions_events
+ * @param Event[] $insertions_events
+ * @param Event[] $updates_events
+ * @param Event[] $map_events
*/
public function testPull(
array $deletions_events,
array $insertions_events,
array $updates_events,
array $map_events
- ) {
+ ): void {
if ($map_events) {
- $slice = round(count($map_events) / 2);
+ $slice = (int) round(count($map_events) / 2);
+
$aggregator1 = $this->getMockBuilder(AggregateEvents::class)->getMock();
$aggregator1
->expects($this->once())
->method('pullEvents')
- ->will($this->returnValue(array_slice($map_events, 0, $slice)));
+ ->willReturn(array_slice($map_events, 0, $slice))
+ ;
$aggregator2 = $this->getMockBuilder(AggregateEvents::class)->getMock();
$aggregator2
->expects($this->once())
->method('pullEvents')
- ->will($this->returnValue(array_slice($map_events, $slice)));
+ ->willReturn(array_slice($map_events, $slice))
+ ;
$map = [
[
@@ -135,22 +137,22 @@ public function testPull(
$this->uow
->expects($this->once())
->method('getScheduledEntityDeletions')
- ->will($this->returnValue($this->getEntitiesFroEvents($deletions_events)))
+ ->willReturn($this->getEntitiesFroEvents($deletions_events))
;
$this->uow
->expects($this->once())
->method('getScheduledEntityInsertions')
- ->will($this->returnValue($this->getEntitiesFroEvents($insertions_events)))
+ ->willReturn($this->getEntitiesFroEvents($insertions_events))
;
$this->uow
->expects($this->once())
->method('getScheduledEntityUpdates')
- ->will($this->returnValue($this->getEntitiesFroEvents($updates_events)))
+ ->willReturn($this->getEntitiesFroEvents($updates_events))
;
$this->uow
->expects($this->once())
->method('getIdentityMap')
- ->will($this->returnValue($map))
+ ->willReturn($map)
;
$expected_events = array_merge(
@@ -168,24 +170,25 @@ public function testPull(
*
* @return object[]
*/
- private function getEntitiesFroEvents(array $events)
+ private function getEntitiesFroEvents(array $events): array
{
if (!$events) {
return [];
}
- $slice = round(count($events) / 2);
+ $slice = (int) round(count($events) / 2);
+
$aggregator1 = $this->getMockBuilder(AggregateEvents::class)->getMock();
$aggregator1
->expects($this->once())
->method('pullEvents')
- ->will($this->returnValue(array_slice($events, 0, $slice)))
+ ->willReturn(array_slice($events, 0, $slice))
;
$aggregator2 = $this->getMockBuilder(AggregateEvents::class)->getMock();
$aggregator2
->expects($this->once())
->method('pullEvents')
- ->will($this->returnValue(array_slice($events, $slice)))
+ ->willReturn(array_slice($events, $slice))
;
return [
diff --git a/tests/Event/Subscriber/DoctrineEventSubscriberTest.php b/tests/Event/Subscriber/DoctrineEventSubscriberTest.php
new file mode 100644
index 0000000..4ea8207
--- /dev/null
+++ b/tests/Event/Subscriber/DoctrineEventSubscriberTest.php
@@ -0,0 +1,95 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Tests\Event\Subscriber;
+
+use Doctrine\ORM\EntityManagerInterface;
+use Doctrine\ORM\Event\OnFlushEventArgs;
+use Doctrine\ORM\Event\PostFlushEventArgs;
+use GpsLab\Bundle\DomainEvent\Event\Publisher;
+use GpsLab\Bundle\DomainEvent\Event\Subscriber\DoctrineEventSubscriber;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+class DoctrineEventSubscriberTest extends TestCase
+{
+ /**
+ * @var MockObject&Publisher
+ */
+ private Publisher $publisher;
+
+ /**
+ * @var MockObject&EntityManagerInterface
+ */
+ private EntityManagerInterface $em;
+
+ private DoctrineEventSubscriber $subscriber;
+
+ protected function setUp(): void
+ {
+ $this->em = $this->getMockBuilder(EntityManagerInterface::class)->getMock();
+ $this->publisher = $this
+ ->getMockBuilder(Publisher::class)
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+
+ $this->subscriber = new DoctrineEventSubscriber($this->publisher);
+ }
+
+ public function testPreFlush(): void
+ {
+ $event = $this
+ ->getMockBuilder(OnFlushEventArgs::class)
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+ $event
+ ->expects($this->once())
+ ->method('getEntityManager')
+ ->willReturn($this->em)
+ ;
+
+ $this->publisher
+ ->expects($this->once())
+ ->method('aggregateEvents')
+ ->with($this->em)
+ ;
+
+ $this->subscriber->onFlush($event);
+ }
+
+ public function testPostFlush(): void
+ {
+ $event = $this
+ ->getMockBuilder(PostFlushEventArgs::class)
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+ $event
+ ->expects($this->atLeastOnce())
+ ->method('getEntityManager')
+ ->willReturn($this->em)
+ ;
+
+ $this->publisher
+ ->expects($this->once())
+ ->method('aggregateEvents')
+ ->with($this->em)
+ ;
+ $this->publisher
+ ->expects($this->once())
+ ->method('dispatchEvents')
+ ->with($this->em)
+ ;
+
+ $this->subscriber->postFlush($event);
+ }
+}
diff --git a/tests/Fixtures/DemoAggregator.php b/tests/Fixtures/DemoAggregator.php
new file mode 100644
index 0000000..d18cea2
--- /dev/null
+++ b/tests/Fixtures/DemoAggregator.php
@@ -0,0 +1,22 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Tests\Fixtures;
+
+use GpsLab\Bundle\DomainEvent\Event\Aggregator\AbstractAggregateEvents;
+use Symfony\Contracts\EventDispatcher\Event;
+
+class DemoAggregator extends AbstractAggregateEvents
+{
+ public function raiseEvent(Event $event): void
+ {
+ $this->raise($event);
+ }
+}
diff --git a/tests/Fixtures/DemoAggregatorRaiseInSelf.php b/tests/Fixtures/DemoAggregatorRaiseInSelf.php
new file mode 100644
index 0000000..b7644cb
--- /dev/null
+++ b/tests/Fixtures/DemoAggregatorRaiseInSelf.php
@@ -0,0 +1,34 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Tests\Fixtures;
+
+use GpsLab\Bundle\DomainEvent\Event\Aggregator\AbstractAggregateEventsRaiseInSelf;
+use Symfony\Contracts\EventDispatcher\Event;
+
+class DemoAggregatorRaiseInSelf extends AbstractAggregateEventsRaiseInSelf
+{
+ private ?Event $raise_in_self_event = null;
+
+ public function raiseEvent(Event $event): void
+ {
+ $this->raise($event);
+ }
+
+ protected function onPurchaseOrderCreated(Event $event): void
+ {
+ $this->raise_in_self_event = $event;
+ }
+
+ public function getRaiseInSelfEvent(): ?Event
+ {
+ return $this->raise_in_self_event;
+ }
+}
diff --git a/tests/Fixtures/Event/Acme_Demo_PurchaseOrderCreated.php b/tests/Fixtures/Event/Acme_Demo_PurchaseOrderCreated.php
new file mode 100644
index 0000000..4c13a43
--- /dev/null
+++ b/tests/Fixtures/Event/Acme_Demo_PurchaseOrderCreated.php
@@ -0,0 +1,15 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+use Symfony\Contracts\EventDispatcher\Event;
+
+class Acme_Demo_PurchaseOrderCreated extends Event
+{
+}
diff --git a/tests/Fixtures/Event/PurchaseOrderCreatedEvent.php b/tests/Fixtures/Event/PurchaseOrderCreatedEvent.php
new file mode 100644
index 0000000..7c2b969
--- /dev/null
+++ b/tests/Fixtures/Event/PurchaseOrderCreatedEvent.php
@@ -0,0 +1,17 @@
+
+ * @license http://opensource.org/licenses/MIT
+ */
+
+namespace GpsLab\Bundle\DomainEvent\Tests\Fixtures\Event;
+
+use Symfony\Contracts\EventDispatcher\Event;
+
+class PurchaseOrderCreatedEvent extends Event
+{
+}
diff --git a/tests/Fixtures/SimpleObject.php b/tests/Fixtures/SimpleObject.php
index ab6e539..e3d8701 100644
--- a/tests/Fixtures/SimpleObject.php
+++ b/tests/Fixtures/SimpleObject.php
@@ -1,55 +1,37 @@
- * @copyright Copyright (c) 2011, Peter Gribanov
- * @license http://opensource.org/licenses/MIT
+ * @author Peter Gribanov
+ * @license http://opensource.org/licenses/MIT
*/
namespace GpsLab\Bundle\DomainEvent\Tests\Fixtures;
class SimpleObject
{
- /**
- * @var string
- */
- private $foo;
-
- /**
- * @var string
- */
- protected $camelCase = 'boo';
-
- /**
- * @return string
- */
- public function getFoo()
+ private string $foo;
+
+ protected string $camelCase = 'boo';
+
+ public function getFoo(): string
{
return $this->foo;
}
- /**
- * @param string $foo
- */
- public function setFoo($foo)
+ public function setFoo(string $foo): void
{
$this->foo = $foo;
}
- /**
- * @return string
- */
- public function getCamelCase()
+ public function getCamelCase(): string
{
return $this->camelCase;
}
- /**
- * @param string $camelCase
- */
- public function setCamelCase($camelCase)
+ public function setCamelCase(string $camelCase): void
{
$this->camelCase = $camelCase;
}
diff --git a/tests/Fixtures/SimpleObjectProxy.php b/tests/Fixtures/SimpleObjectProxy.php
index a921bfe..eedf0f5 100644
--- a/tests/Fixtures/SimpleObjectProxy.php
+++ b/tests/Fixtures/SimpleObjectProxy.php
@@ -1,11 +1,11 @@
- * @copyright Copyright (c) 2011, Peter Gribanov
- * @license http://opensource.org/licenses/MIT
+ * @author Peter Gribanov
+ * @license http://opensource.org/licenses/MIT
*/
namespace GpsLab\Bundle\DomainEvent\Tests\Fixtures;
diff --git a/tests/GpsLabDomainEventBundleTest.php b/tests/GpsLabDomainEventBundleTest.php
index 8510371..07db886 100644
--- a/tests/GpsLabDomainEventBundleTest.php
+++ b/tests/GpsLabDomainEventBundleTest.php
@@ -1,4 +1,5 @@
bundle = new GpsLabDomainEventBundle();
- $this->container = new ContainerBuilder();
}
- public function testCorrectBundle()
+ public function testCorrectBundle(): void
{
$this->assertInstanceOf(Bundle::class, $this->bundle);
}
- public function testBuild()
- {
- $this->bundle->build($this->container);
-
- $has_event_listener_pass = false;
- foreach ($this->container->getCompiler()->getPassConfig()->getBeforeOptimizationPasses() as $pass) {
- $has_event_listener_pass = $pass instanceof EventListenerPass ?: $has_event_listener_pass;
- }
- $this->assertTrue($has_event_listener_pass);
- }
-
- public function testContainerExtension()
+ public function testContainerExtension(): void
{
$this->assertInstanceOf(GpsLabDomainEventExtension::class, $this->bundle->getContainerExtension());
}
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index 5dea307..112bd97 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -1,4 +1,5 @@