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

CommitSequence::makeEmpty()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
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\EventStore;
12
13
use Countable;
14
use Ds\Vector;
15
use Iterator;
16
use IteratorAggregate;
17
18
final class CommitSequence implements IteratorAggregate, Countable
19
{
20
    /** @var Vector */
21
    private $compositeVector;
22
23
    public static function fromArray(array $commitsArray): CommitSequence
24
    {
25
        return new static(array_map(function (array $commitState) {
26
            return Commit::fromArray($commitState);
27
        }, $commitsArray));
28
    }
29
30 1
    public static function makeEmpty(): CommitSequence
31
    {
32 1
        return new self;
33
    }
34
35 2
    public function __construct(array $commits = [])
36
    {
37
        $this->compositeVector = (function (CommitInterface ...$commits): Vector {
38 2
            return new Vector($commits);
39 2
        })(...$commits);
40 2
    }
41
42
    public function push(CommitInterface $commit): self
43
    {
44
        if (!$this->isEmpty()) {
45
            $nextRevision = $this->getHead()->getAggregateRevision()->increment();
46
            if (!$nextRevision->equals($commit->getAggregateRevision())) {
47
                throw new \Exception(sprintf(
48
                    "Trying to add unexpected revision %s to event-sequence. Expected revision is $nextRevision",
49
                    $commit->getAggregateRevision()
50
                ));
51
            }
52
        }
53
        $commitSequence = clone $this;
54
        $commitSequence->compositeVector->push($commit);
55
        return $commitSequence;
56
    }
57
58
    public function toNative(): array
59
    {
60
        return array_map(function (CommitInterface $commit): array {
61
            $nativeRep = $commit->toArray();
62
            $nativeRep["@type"] = get_class($commit);
63
            return $nativeRep;
64
        }, $this->compositeVector->toArray());
65
    }
66
67
    public function getTail(): ?CommitInterface
68
    {
69
        return $this->isEmpty() ? null : $this->compositeVector->first();
70
    }
71
72
    public function getHead(): ?CommitInterface
73
    {
74
        return $this->isEmpty() ? null : $this->compositeVector->last();
75
    }
76
77
    public function get(StreamRevision $streamRevision): ?CommitInterface
78
    {
79
        if ($this->compositeVector->offsetExists($streamRevision->toNative() - 1)) {
80
            $this->compositeVector->get($streamRevision->toNative() - 1);
81
        }
82
        return null;
83
    }
84
85
    public function getSlice(StreamRevision $start, StreamRevision $end): self
86
    {
87
        return $this->compositeVector->reduce(
88
            function (CommitSequence $commits, CommitInterface $commit) use ($start, $end): CommitSequence {
89
                if ($commit->getStreamRevision()->isWithinRange($start, $end)) {
90
                    $commits = $commits->push($commit); /* @var CommitSequence $commits */
91
                    return $commits;
92
                }
93
                return $commits;
94
            },
95
            new static
96
        );
97
    }
98
99
    public function isEmpty(): bool
100
    {
101
        return $this->compositeVector->isEmpty();
102
    }
103
104
    public function revisionOf(CommitInterface $commit): StreamRevision
105
    {
106
        return StreamRevision::fromNative($this->compositeVector->find($commit));
107
    }
108
109
    public function getLength(): int
110
    {
111
        return $this->count();
112
    }
113
114
    public function count(): int
115
    {
116
        return $this->compositeVector->count();
117
    }
118
119 2
    public function getIterator(): Iterator
120
    {
121 2
        return $this->compositeVector->getIterator();
122
    }
123
124
    private function __clone()
125
    {
126
        $this->compositeVector = clone $this->compositeVector;
127
    }
128
}
129