Completed
Pull Request — master (#35)
by Frank
03:22
created

ConstructingAggregateRootRepository::persist()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 8
ccs 6
cts 6
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace EventSauce\EventSourcing;
6
7
use function assert;
8
use Generator;
9
10
final class ConstructingAggregateRootRepository implements AggregateRootRepository
11
{
12
    /**
13
     * @var string
14
     */
15
    private $aggregateRootClassName;
16
17
    /**
18
     * @var MessageRepository
19
     */
20
    private $repository;
21
22
    /**
23
     * @var MessageDecorator
24
     */
25
    private $decorator;
26
27
    /**
28
     * @var MessageDispatcher
29
     */
30
    private $dispatcher;
31
32 10
    public function __construct(
33
        string $aggregateRootClassName,
34
        MessageRepository $messageRepository,
35
        MessageDispatcher $dispatcher = null,
36
        MessageDecorator $decorator = null
37
    ) {
38 10
        $this->aggregateRootClassName = $aggregateRootClassName;
39 10
        $this->repository = $messageRepository;
40 10
        $this->dispatcher = $dispatcher ?: new SynchronousMessageDispatcher();
41 10
        $this->decorator = $decorator ?: new DefaultHeadersDecorator();
42 10
    }
43
44 8
    public function retrieve(AggregateRootId $aggregateRootId): object
45
    {
46
        /** @var AggregateRoot $className */
47 8
        $className = $this->aggregateRootClassName;
48 8
        $events = $this->retrieveAllEvents($aggregateRootId);
49
50 8
        return $className::reconstituteFromEvents($aggregateRootId, $events);
51
    }
52
53 8
    private function retrieveAllEvents(AggregateRootId $aggregateRootId): Generator
54
    {
55
        /** @var Message $message */
56 8
        foreach ($this->repository->retrieveAll($aggregateRootId) as $message) {
57 2
            yield $message->event();
58
        }
59 8
    }
60
61 8
    public function persist(object $aggregateRoot)
62
    {
63 8
        assert($aggregateRoot instanceof AggregateRoot, "Expected \$aggregateRoot to be an instance of " . AggregateRoot::class);
64
65 8
        $this->persistEvents(
66 8
            $aggregateRoot->aggregateRootId(),
67 8
            $aggregateRoot->aggregateRootVersion(),
68 8
            ...$aggregateRoot->releaseEvents()
69
        );
70 8
    }
71
72 8
    public function persistEvents(AggregateRootId $aggregateRootId, int $aggregateRootVersion, object ...$events)
73
    {
74 8
        $metadata = [Header::AGGREGATE_ROOT_ID => $aggregateRootId];
75 8
        $messages = array_map(function (object $event) use ($metadata, &$aggregateRootVersion) {
76 4
            return $this->decorator->decorate(new Message(
77 4
                $event,
78 4
                $metadata + [Header::AGGREGATE_ROOT_VERSION => ++$aggregateRootVersion]
79
            ));
80 8
        }, $events);
81
82 8
        $this->repository->persist(...$messages);
83 8
        $this->dispatcher->dispatch(...$messages);
84 8
    }
85
}
86