Passed
Push — master ( 6d1632...ddd5df )
by Thorsten
01:48
created

DomainEventSequence::indexOf()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
/**
3
 * This file is part of the daikon-cqrs/cqrs project.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
declare(strict_types=1);
10
11
namespace Daikon\EventSourcing\Aggregate;
12
13
use Countable;
14
use Ds\Vector;
15
use Iterator;
16
use IteratorAggregate;
17
18
final class DomainEventSequence implements IteratorAggregate, Countable
19
{
20
    /** @var Vector */
21
    private $compositeVector;
22
23 1
    public static function fromArray(array $eventsArray): DomainEventSequence
24
    {
25
        return new static(array_map(function (array $eventState): DomainEventInterface {
26 1
            $eventFqcn = self::resolveEventFqcn($eventState);
27 1
            return call_user_func([ $eventFqcn, 'fromArray' ], $eventState);
28 1
        }, $eventsArray));
29
    }
30
31 6
    public static function makeEmpty(): DomainEventSequence
32
    {
33 6
        return new self;
34
    }
35
36
    public function __construct(array $events = [])
37
    {
38 6
        $this->compositeVector = (function (DomainEventInterface ...$events): Vector {
39 6
            return new Vector($events);
40 6
        })(...$events);
41 6
    }
42
43 3
    public function push(DomainEventInterface $event): DomainEventSequence
44
    {
45 3
        $expectedRevision = $this->getHeadRevision()->increment();
46 3
        if (!$this->isEmpty() && !$expectedRevision->equals($event->getAggregateRevision())) {
47
            throw new \Exception(sprintf(
48
                'Trying to add unexpected revision %s to event-sequence. Expected revision is %s',
49
                $event->getAggregateRevision(),
50
                $expectedRevision
51
            ));
52
        }
53 3
        $eventSequence = clone $this;
54 3
        $eventSequence->compositeVector->push($event);
55 3
        return $eventSequence;
56
    }
57
58
    public function append(DomainEventSequence $events): DomainEventSequence
59
    {
60
        $eventSequence = clone $this;
61
        foreach ($events as $event) {
62
            $eventSequence = $eventSequence->push($event);
63
        }
64
        return $eventSequence;
65
    }
66
67 1
    public function toNative(): array
68
    {
69 1
        $nativeList = [];
70 1
        foreach ($this as $event) {
71 1
            $nativeRep = $event->toArray();
72 1
            $nativeRep['@type'] = get_class($event);
73 1
            $nativeList[] = $nativeRep;
74
        }
75 1
        return $nativeList;
76
    }
77
78 3
    public function getHeadRevision(): AggregateRevision
79
    {
80 3
        return $this->isEmpty() ? AggregateRevision::makeEmpty() : $this->getHead()->getAggregateRevision();
81
    }
82
83
    public function getTailRevision(): AggregateRevision
84
    {
85
        return $this->isEmpty() ? AggregateRevision::makeEmpty() : $this->getTail()->getAggregateRevision();
86
    }
87
88
    public function getTail(): ?DomainEventInterface
89
    {
90
        return $this->compositeVector->first();
91
    }
92
93
    public function getHead(): ?DomainEventInterface
94
    {
95
        return $this->compositeVector->last();
96
    }
97
98
    public function getLength(): int
99
    {
100
        return $this->count();
101
    }
102
103 3
    public function isEmpty(): bool
104
    {
105 3
        return $this->compositeVector->isEmpty();
106
    }
107
108
    public function indexOf(DomainEventInterface $event): int
109
    {
110
        return $this->compositeVector->find($event);
111
    }
112
113 2
    public function count(): int
114
    {
115 2
        return $this->compositeVector->count();
116
    }
117
118 4
    public function getIterator(): Iterator
119
    {
120 4
        return $this->compositeVector->getIterator();
121
    }
122
123 1
    private static function resolveEventFqcn(array $eventState): string
124
    {
125 1
        if (!isset($eventState['@type'])) {
126
            throw new \Exception('Missing expected typeinfo for event at key "@type" within given state-array.');
127
        }
128 1
        $eventFqcn = $eventState['@type'];
129 1
        if (!class_exists($eventFqcn)) {
130
            throw new \Exception(sprintf('Can not load event-class "%s" given within state-array.', $eventFqcn));
131
        }
132 1
        return $eventFqcn;
133
    }
134
135 3
    private function __clone()
136
    {
137 3
        $this->compositeVector = clone $this->compositeVector;
138 3
    }
139
}
140