Passed
Push — master ( 1770a8...56fedc )
by Constantin
03:21
created

InMemoryEventStore::findEventById()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 21
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 21
c 0
b 0
f 0
ccs 7
cts 7
cp 1
rs 8.7624
cc 5
eloc 7
nc 5
nop 1
crap 5
1
<?php
2
3
4
namespace Gica\Cqrs\EventStore\InMemory;
5
6
7
use Gica\Cqrs\Event\EventWithMetaData;
8
use Gica\Cqrs\Event\MetaData;
9
use Gica\Cqrs\EventStore;
10
use Gica\Cqrs\EventStore\AggregateEventStream;
11
use Gica\Cqrs\EventStore\EventsCommit;
12
use Gica\Cqrs\EventStore\EventStreamGroupedByCommit;
13
use Gica\Cqrs\EventStore\Exception\ConcurrentModificationException;
14
use Gica\Iterator\IteratorTransformer\IteratorExpander;
15
use Gica\Types\Guid;
16
17
class InMemoryEventStore implements EventStore
18
{
19
    /** @var EventsCommit[] */
20
    public $commitsByAggregate = [];
21
    private $versions = [];
22
    private $latestSequence = 0;
23
24 10
    public function loadEventsForAggregate(string $aggregateClass, $aggregateId): AggregateEventStream
25
    {
26 10
        return new InMemoryAggregateEventStream(
27 10
            $this->getEventsArrayForAggregate($aggregateClass, $aggregateId), $aggregateClass, $aggregateId, $this->latestSequence);
28
    }
29
30
    /**
31
     * @inheritdoc
32
     */
33 10
    public function appendEventsForAggregate($aggregateId, string $aggregateClass, $eventsWithMetaData, int $expectedVersion, int $expectedSequence)
34
    {
35 10
        if ($this->getAggregateVersion($aggregateClass, $aggregateId) != $expectedVersion) {
36 1
            throw new ConcurrentModificationException();
37
        }
38
39 10
        $this->appendEventsForAggregateWithoutChecking($aggregateId, $aggregateClass, $eventsWithMetaData, $expectedVersion, $expectedSequence);
40 10
    }
41
42 11
    public function appendEventsForAggregateWithoutChecking($aggregateId, $aggregateClass, $newEvents, int $expectedVersion, int $expectedSequence)
43
    {
44 11
        $this->addEventsToArrayForAggregate(
45 11
            $aggregateId,
46 11
            $aggregateClass,
47 11
            $this->decorateEventsWithMetadata($aggregateClass, $aggregateId, $newEvents),
48 11
            $expectedVersion,
49 11
            $expectedSequence
50
        );
51
52 11
        $constructKey = $this->constructKey($aggregateClass, $aggregateId);
53
54 11
        if (!isset($this->versions[$constructKey])) {
55 11
            $this->versions[$constructKey] = 0;
56
        }
57
58 11
        $this->versions[$constructKey]++;
59 11
        $this->latestSequence++;
60 11
    }
61
62 10
    private function getEventsArrayForAggregate(string $aggregateClass, $aggregateId)
63
    {
64 10
        $aggregateKey = $this->constructKey($aggregateClass, $aggregateId);
65
66 10
        return isset($this->commitsByAggregate[$aggregateKey])
67 6
            ? $this->extractEventsFromCommits($this->commitsByAggregate[$aggregateKey])
0 ignored issues
show
Documentation introduced by
$this->commitsByAggregate[$aggregateKey] is of type object<Gica\Cqrs\EventStore\EventsCommit>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
68 10
            : [];
69
    }
70
71 11
    private function addEventsToArrayForAggregate($aggregateId, $aggregateClass, $newEvents, int $expectedVersion, int $expectedSequence)
72
    {
73 11
        $this->commitsByAggregate[$this->constructKey($aggregateClass, $aggregateId)][] = new EventsCommit(
74 11
            $expectedSequence, $expectedVersion, $newEvents
75
        );
76 11
    }
77
78
    public function loadEventsByClassNames(array $eventClasses): EventStreamGroupedByCommit
79
    {
80 1
        $commits = iterator_to_array((new IteratorExpander(function ($aggregateCommits) {
81 1
            yield from $aggregateCommits;
82 1
        }))($this->commitsByAggregate));
83
84 1
        return new FilteredRawEventStreamGroupedByCommit($commits, $eventClasses);
85
    }
86
87
    private function extractEventsFromCommits(array $commits = [])
88
    {
89 6
        $eventsExtracter = new IteratorExpander(function (EventsCommit $commit) {
90 6
            yield from $commit->getEventsWithMetadata();
91 6
        });
92
93 6
        return iterator_to_array($eventsExtracter($commits));
94
    }
95
96 11
    public function getAggregateVersion(string $aggregateClass, $aggregateId)
97
    {
98 11
        $key = $this->constructKey($aggregateClass, $aggregateId);
99
100 11
        return isset($this->versions[$key]) ? $this->versions[$key] : 0;
101
    }
102
103
    /**
104
     * @param $aggregateClass
105
     * @param $aggregateId
106
     * @param $priorEvents
107
     * @return EventWithMetaData[]
108
     */
109
    public function decorateEventsWithMetadata($aggregateClass, $aggregateId, array $priorEvents)
110
    {
111 11
        return array_map(function ($event) use ($aggregateClass, $aggregateId) {
112 11
            if ($event instanceof EventWithMetaData) {
113 10
                return $event;
114
            }
115
116 5
            return new EventWithMetaData($event, new MetaData(
117 5
                $aggregateId,
118 5
                    $aggregateClass,
119 5
                    new \DateTimeImmutable(),
120 5
                    null
121
            ));
122 11
        }, $priorEvents);
123
    }
124
125 3
    public function fetchLatestSequence(): int
126
    {
127 3
        return $this->latestSequence;
128
    }
129
130 14
    private function constructKey(string $aggregateClass, $aggregateId): string
131
    {
132 14
        return $aggregateClass . '_' . (string)$aggregateId;
133
    }
134
135 1
    public function findEventById(string $eventId): ?EventWithMetaData
136
    {
137 1
        foreach($this->commitsByAggregate as $commits)
138
        {
139 1
            foreach($commits as $commit)
0 ignored issues
show
Bug introduced by
The expression $commits of type object<Gica\Cqrs\EventStore\EventsCommit> is not traversable.
Loading history...
140
            {
141
                /** @var \Gica\Cqrs\EventStore\EventsCommit $commit */
142
143 1
                foreach($commit->getEventsWithMetadata() as $eventWithMetadata)
144
                {
145 1
                    if($eventWithMetadata->getMetaData()->getEventId() === $eventId)
146
                    {
147 1
                        return $eventWithMetadata;
148
                    }
149
                }
150
            }
151
152
        }
153
154 1
        return null;
155
    }
156
}