Completed
Push — master ( 14e29f...efb36f )
by David
02:04
created

InMemoryEventStore::getClassForKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4286
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Rawkode\Eidetic\EventStore\InMemoryEventStore;
4
5
use Rawkode\Eidetic\EventStore\InvalidEventException;
6
use Rawkode\Eidetic\EventStore\EventStore;
7
use Rawkode\Eidetic\EventStore\EventPublisherMixin;
8
use Rawkode\Eidetic\EventStore\NoEventsFoundForKeyException;
9
use Rawkode\Eidetic\EventStore\Subscriber;
10
use Rawkode\Eidetic\EventStore\VerifyEventIsAClassTrait;
11
use Rawkode\Eidetic\EventStore\InMemoryEventStore\TransactionAlreadyInProgressException;
12
use Rawkode\Eidetic\EventStore\EventPublisher;
13
use Doctrine\Common\EventSubscriber;
14
15
final class InMemoryEventStore implements EventStore
16
{
17
    use EventPublisherMixin;
18
    use VerifyEventIsAClassTrait;
19
20
    /**
21
     * @var int
22
     */
23
    private $serialNumber = 0;
24
25
    /**
26
     * @var array
27
     */
28
    private $events = [];
29
30
    /**
31
     * @var array
32
     */
33
    private $transactionBackup = [];
34
35
    /**
36
     * @var array
37
     */
38
    private $stagedEvents = [];
39
40
    /**
41
     * @param string $key
42
     *
43
     * @return array
44
     */
45 2
    public function retrieve($key)
46
    {
47 2
        $eventLogs = $this->eventLogs($key);
48
49 1
        return array_map(function ($eventLog) {
50 1
            return $eventLog['event'];
51 1
        }, $eventLogs);
52
    }
53
54
    /**
55
     * @param string $key
56
     *
57
     * @return array
58
     */
59 1
    public function retrieveLogs($key)
60
    {
61 1
        return $this->eventLogs($key);
62
    }
63
64
    /**
65
     * @param string $key
66
     *
67
     * @throws NoEventsFoundForKeyException
68
     *
69
     * @return array
70
     */
71 3
    private function eventLogs($key)
72
    {
73 3
        $this->verifyEventExistsForKey($key);
74
75 2
        return $this->events[$key];
76
    }
77
78
    /**
79
     * @param string $key
80
     * @param array $events
81
     *
82
     * @throws TransactionAlreadyInProgressException
83
     * @throws InvalidEventException
84
     */
85 6
    public function store($key, array $events)
86
    {
87
        try {
88 6
            $this->startTransaction();
89
90 6
            foreach ($events as $event) {
91 6
                $this->persistEvent($key, $event);
92 6
            }
93 6
        } catch (InvalidEventException $invalidEventException) {
94 2
            $this->abortTransaction();
95
96 2
            throw $invalidEventException;
97
        }
98
99 5
        $this->completeTransaction();
100 5
    }
101
102
    /**
103
     * @throws TransactionAlreadyInProgressException
104
     */
105 6
    private function startTransaction()
106
    {
107 6
        $this->transactionBackup = $this->events;
108 6
        $this->stagedEvents = [];
109 6
    }
110
111
    /**
112
     */
113 2
    private function abortTransaction()
114
    {
115 2
        $this->events = $this->transactionBackup;
116 2
        $this->stagedEvents = [];
117 2
    }
118
119
    /**
120
     */
121 5
    private function completeTransaction()
122
    {
123 5
        $this->transactionBackup = [];
124
125 5
        foreach ($this->stagedEvents as $event) {
126 5
            $this->publish(self::EVENT_STORED, $event);
127 5
        }
128
129 5
        $this->stagedEvents = [];
130 5
    }
131
132
    /**
133
     * @param string $key
134
     * @param  $event
135
     *
136
     * @throws InvalidEventException
137
     */
138 6
    private function persistEvent($key, $event)
139
    {
140 6
        $this->verifyEventIsAClass($event);
141
142 6
        $this->events[$key][] = [
143 6
            'serial_number' => ++$this->serialNumber,
144 6
            'key' => $key,
145 6
            'recorded_at' => new \DateTime('now', new \DateTimeZone('UTC')),
146 6
            'event_class' => get_class($event),
147 6
            'event' => $event,
148
        ];
149
150 6
        array_push($this->stagedEvents, $event);
151 6
    }
152
153
154
    /**
155
     * @param $key
156
     * @return string
157
     */
158 1
    public function getClassForKey($key)
159
    {
160 1
        $this->verifyEventExistsForKey($key);
161
162 1
        return get_class($this->events[$key][0]['event']);
163
    }
164
165
    /**
166
     * @param $key
167
     * @throws NoEventsFoundForKeyException
168
     */
169 4
    private function verifyEventExistsForKey($key)
170
    {
171 4
        if (false === array_key_exists($key, $this->events)) {
172 1
            throw new NoEventsFoundForKeyException();
173
        }
174 3
    }
175
}
176