Passed
Push — master ( 81835c...bfb296 )
by Thorsten
03:09
created

CommitSequence::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 5
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
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\EventStore\Commit;
12
13
use Daikon\EventSourcing\EventStore\Stream\StreamRevision;
14
use Ds\Vector;
15
use Iterator;
16
17
final class CommitSequence implements CommitSequenceInterface
18
{
19
    /** @var Vector */
20
    private $compositeVector;
21
22
    public static function fromArray(array $commitsArray): CommitSequenceInterface
23
    {
24
        return new static(array_map(function (array $commitState): CommitInterface {
25
            return Commit::fromArray($commitState);
26
        }, $commitsArray));
27
    }
28
29
    public static function makeEmpty(): CommitSequenceInterface
30
    {
31
        return new self;
32
    }
33
34
    public function __construct(array $commits = [])
35
    {
36
        $this->compositeVector = (function (CommitInterface ...$commits): Vector {
37
            return new Vector($commits);
38
        })(...$commits);
39
    }
40
41
    public function push(CommitInterface $commit): CommitSequenceInterface
42
    {
43
        if (!$this->isEmpty()) {
44
            $nextRevision = $this->getHead()->getAggregateRevision()->increment();
45
            if (!$nextRevision->equals($commit->getAggregateRevision())) {
46
                throw new \Exception(sprintf(
47
                    'Trying to add unexpected revision %s to event-sequence. Expected revision is %s',
48
                    $commit->getAggregateRevision(),
49
                    $nextRevision
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): CommitSequenceInterface
86
    {
87
        return $this->compositeVector->reduce(function (
88
            CommitSequenceInterface $commits,
89
            CommitInterface $commit
90
        ) use (
91
            $start,
92
            $end
93
        ): CommitSequenceInterface {
94
            if ($commit->getStreamRevision()->isWithinRange($start, $end)) {
95
                /* @var CommitSequenceInterface $commits */
96
                $commits = $commits->push($commit);
97
                return $commits;
98
            }
99
            return $commits;
100
        }, new static);
101
    }
102
103
    public function isEmpty(): bool
104
    {
105
        return $this->compositeVector->isEmpty();
106
    }
107
108
    public function revisionOf(CommitInterface $commit): StreamRevision
109
    {
110
        return StreamRevision::fromNative($this->compositeVector->find($commit));
111
    }
112
113
    public function getLength(): int
114
    {
115
        return $this->count();
116
    }
117
118
    public function count(): int
119
    {
120
        return $this->compositeVector->count();
121
    }
122
123
    public function getIterator(): Iterator
124
    {
125
        return $this->compositeVector->getIterator();
126
    }
127
128
    private function __clone()
129
    {
130
        $this->compositeVector = clone $this->compositeVector;
131
    }
132
}
133