AggregateReconstructor::reconstitute()   B
last analyzed

Complexity

Conditions 7
Paths 10

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 30
ccs 16
cts 16
cp 1
rs 8.5066
c 0
b 0
f 0
cc 7
nc 10
nop 3
crap 7
1
<?php
2
3
namespace DDDominio\EventSourcing\Common;
4
5
use DDDominio\EventSourcing\Common\Annotation\AggregateDeleter;
6
use DDDominio\EventSourcing\Snapshotting\SnapshotInterface;
7
use DDDominio\EventSourcing\Snapshotting\Snapshotter;
8
use Doctrine\Common\Annotations\AnnotationReader;
9
10
class AggregateReconstructor
11
{
12
    /**
13
     * @var Snapshotter
14
     */
15
    private $snapshooter;
16
17
    /**
18
     * @var AnnotationReader
19
     */
20
    private $annotationReader;
21
22
    /**
23
     * @param Snapshotter $snapshotter
24
     */
25 7
    public function __construct($snapshotter)
26
    {
27 7
        $this->snapshooter = $snapshotter;
28 7
        $this->annotationReader = new AnnotationReader();
29 7
    }
30
31
    /**
32
     * @param string $class
33
     * @param EventStreamInterface $eventStream
34
     * @param SnapshotInterface $snapshot
35
     * @return EventSourcedAggregateRootInterface
36
     */
37 7
    public function reconstitute($class, $eventStream, $snapshot = null)
38
    {
39 7
        $this->assertValidClass($class);
40
41 6
        if (is_null($snapshot) && $eventStream->isEmpty()) {
42 1
            return null;
43
        }
44
45 5
        if (!$eventStream->isEmpty()) {
46 4
            $aggregateDeleterAnnotation = $this->annotationReader->getClassAnnotation(
47 4
                new \ReflectionClass(get_class($eventStream->last())),
48 4
                AggregateDeleter::class
49
            );
50 4
            if (!is_null($aggregateDeleterAnnotation)) {
51 1
                return null;
52
            }
53
        }
54
55 4
        if ($snapshot instanceof SnapshotInterface) {
56 2
            $aggregate = $this->snapshooter->translateSnapshot($snapshot);
57
        } else {
58 2
            $aggregate = $this->buildEmptyAggregate($class);
59
        }
60
61 4
        foreach ($eventStream as $event) {
62 3
            $aggregate->apply($event);
63
        }
64
65 4
        return $aggregate;
66
    }
67
68
    /**
69
     * @param string $class
70
     */
71 7
    private function assertValidClass($class)
72
    {
73 7
        $reflectedClass = new \ReflectionClass($class);
74
75 7
        $parentClass = $reflectedClass->getParentClass();
76
77 7
        if (EventSourcedAggregateRoot::class !== $parentClass->getName()) {
78 1
            throw new \InvalidArgumentException();
79
        }
80 6
    }
81
82
    /**
83
     * @param string $class
84
     * @return EventSourcedAggregateRootInterface
85
     */
86 2
    private function buildEmptyAggregate($class)
87
    {
88 2
        return (new \ReflectionClass($class))->newInstanceWithoutConstructor();
89
    }
90
}
91