1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace RemotelyLiving\PHPCommandBus; |
6
|
|
|
|
7
|
|
|
use Psr\EventDispatcher; |
8
|
|
|
use RemotelyLiving\PHPCommandBus\Interfaces; |
9
|
|
|
|
10
|
|
|
final class CommandBus implements Interfaces\CommandBus |
11
|
|
|
{ |
12
|
|
|
private Interfaces\Resolver $resolver; |
13
|
|
|
|
14
|
|
|
private EventDispatcher\EventDispatcherInterface $eventDispatcher; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* @var callable |
18
|
|
|
*/ |
19
|
|
|
private $callStack; |
20
|
|
|
|
21
|
|
|
public function __construct( |
22
|
|
|
Interfaces\Resolver $resolver, |
23
|
|
|
EventDispatcher\EventDispatcherInterface $eventDispatcher = null |
24
|
|
|
) { |
25
|
|
|
$this->resolver = $resolver; |
26
|
|
|
$this->eventDispatcher = $eventDispatcher ?? $this->createDummyDispatcher(); |
27
|
|
|
$this->callStack = $this->seedCallStack(); |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
public static function create( |
31
|
|
|
Interfaces\Resolver $resolver, |
32
|
|
|
EventDispatcher\EventDispatcherInterface $eventDispatcher = null |
33
|
|
|
): self { |
34
|
|
|
return new static($resolver, $eventDispatcher); |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
public function pushMiddleware(callable $middleware): Interfaces\CommandBus |
38
|
|
|
{ |
39
|
|
|
$next = $this->callStack; |
40
|
|
|
|
41
|
|
|
$this->callStack = function (object $command) use ($middleware, $next): void { |
42
|
|
|
$middleware($command, $next); |
43
|
|
|
}; |
44
|
|
|
|
45
|
|
|
return $this; |
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
public function handle(object $command): void |
49
|
|
|
{ |
50
|
|
|
($this->callStack)($command); |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
private function seedCallStack(): callable |
54
|
|
|
{ |
55
|
|
|
return function (object $command): void { |
56
|
|
|
$possibleEvents = $this->resolver->resolve($command)->handle($command, $this); |
57
|
|
|
if (!$possibleEvents || !is_iterable($possibleEvents)) { |
|
|
|
|
58
|
|
|
return; |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
foreach ($possibleEvents as $event) { |
62
|
|
|
$this->eventDispatcher->dispatch($event); |
63
|
|
|
} |
64
|
|
|
}; |
65
|
|
|
} |
66
|
|
|
|
67
|
|
|
private function createDummyDispatcher(): EventDispatcher\EventDispatcherInterface |
68
|
|
|
{ |
69
|
|
|
return (new class implements EventDispatcher\EventDispatcherInterface { |
70
|
|
|
public function dispatch(object $event) |
71
|
|
|
{ |
72
|
|
|
return $event; |
73
|
|
|
} |
74
|
|
|
}); |
75
|
|
|
} |
76
|
|
|
} |
77
|
|
|
|