CommandEventDispatcher::handle()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 12
rs 9.4285
cc 2
eloc 6
nc 2
nop 1
1
<?php
2
3
namespace PhpDDD\DomainDrivenDesign\Domain;
4
5
use PhpDDD\DomainDrivenDesign\Command\AbstractCommand;
6
use PhpDDD\DomainDrivenDesign\Command\CommandDispatcherInterface;
7
use PhpDDD\DomainDrivenDesign\Command\CommandHandlerInterface;
8
use PhpDDD\DomainDrivenDesign\Event\AbstractEvent;
9
use PhpDDD\DomainDrivenDesign\Event\EventDispatcherInterface;
10
use PhpDDD\DomainDrivenDesign\Event\EventSubscriberInterface;
11
12
/**
13
 * The CommandEventDispatcher allows you to handle the flow from a Command to the events publication.
14
 */
15
final class CommandEventDispatcher implements CommandDispatcherInterface, EventDispatcherInterface
16
{
17
    /**
18
     * @var CommandDispatcherInterface
19
     */
20
    private $commandDispatcher;
21
    /**
22
     * @var EventDispatcherInterface
23
     */
24
    private $eventDispatcher;
25
26
    /**
27
     * @param CommandDispatcherInterface $commandDispatcher
28
     * @param EventDispatcherInterface   $eventDispatcher
29
     */
30
    public function __construct(
31
        CommandDispatcherInterface $commandDispatcher,
32
        EventDispatcherInterface $eventDispatcher
33
    ) {
34
        $this->commandDispatcher = $commandDispatcher;
35
        $this->eventDispatcher   = $eventDispatcher;
36
    }
37
38
    /**
39
     * Try to handle the command given in argument.
40
     * It will look over every handlers registered and find the one that knows how handle it.
41
     *
42
     * @param AbstractCommand $command
43
     *
44
     * @return AbstractCommand
45
     */
46
    public function handle(AbstractCommand $command)
47
    {
48
        $this->commandDispatcher->handle($command);
49
        // Now that the command is handled, let's found if there is some events to publish
50
        $events = $this->extractEventsFromCommand($command);
51
        foreach ($events as $event) {
52
            // we will only publish event to synchronous listeners
53
            $this->publish($event);
54
        }
55
56
        return $command;
57
    }
58
59
    /**
60
     * Register a CommandHandler for one or more Command.
61
     *
62
     * @param CommandHandlerInterface $handler
63
     *
64
     * @return void
65
     */
66
    public function register(CommandHandlerInterface $handler)
67
    {
68
        $this->commandDispatcher->register($handler);
69
    }
70
71
    /**
72
     * @param AbstractEvent $event
73
     * @param bool          $asynchronous
74
     *
75
     * @return AbstractEvent
76
     */
77
    public function publish(AbstractEvent $event, $asynchronous = false)
78
    {
79
        return $this->eventDispatcher->publish($event, $asynchronous);
80
    }
81
82
    /**
83
     * @param EventSubscriberInterface $subscriber
84
     */
85
    public function subscribe(EventSubscriberInterface $subscriber)
86
    {
87
        $this->eventDispatcher->subscribe($subscriber);
88
    }
89
90
    /**
91
     * @param AbstractCommand $command
92
     *
93
     * @return AbstractEvent[]
94
     */
95
    private function extractEventsFromCommand(AbstractCommand $command)
96
    {
97
        $events = [];
98
        foreach ($command->aggregateRoots as $aggregateRoot) {
99
            $events = array_merge($events, $aggregateRoot->pullEvents());
100
        }
101
102
        return $events;
103
    }
104
}
105