Completed
Push — master ( 00f04e...1d93d6 )
by Freek
03:46
created

AggregateRoot   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 0
Metric Value
wmc 10
lcom 1
cbo 6
dl 0
loc 106
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Spatie\EventSourcing;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Str;
7
8
abstract class AggregateRoot
9
{
10
    /** @var string */
11
    private string $aggregateUuid;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
12
13
    /** @var array */
14
    private array $recordedEvents = [];
15
16
    /**
17
     * @param  string  $uuid
18
     * @return static
19
     */
20
    public static function retrieve(string $uuid): AggregateRoot
21
    {
22
        $aggregateRoot = (new static());
23
24
        $aggregateRoot->aggregateUuid = $uuid;
25
26
        return $aggregateRoot->reconstituteFromEvents();
27
    }
28
29
    /**
30
     * @param  ShouldBeStored  $domainEvent
31
     * @return static
32
     */
33
    public function recordThat(ShouldBeStored $domainEvent): AggregateRoot
34
    {
35
        $this->recordedEvents[] = $domainEvent;
36
37
        $this->apply($domainEvent);
38
39
        return $this;
40
    }
41
42
    /**
43
     * @return static
44
     */
45
    public function persist(): AggregateRoot
46
    {
47
        $storedEvents = call_user_func(
48
            [$this->getStoredEventRepository(), 'persistMany'],
49
            $this->getAndClearRecordedEvents(),
50
            $this->aggregateUuid ?? ''
51
        );
52
53
        $storedEvents->each(function (StoredEvent $storedEvent) {
54
            $storedEvent->handle();
55
        });
56
57
        return $this;
58
    }
59
60
    protected function getStoredEventRepository(): StoredEventRepository
61
    {
62
        return app($this->storedEventRepository ?? config('event-sourcing.stored_event_repository'));
63
    }
64
65
    public function getRecordedEvents(): array
66
    {
67
        return $this->recordedEvents;
68
    }
69
70
    private function getAndClearRecordedEvents(): array
71
    {
72
        $recordedEvents = $this->recordedEvents;
73
74
        $this->recordedEvents = [];
75
76
        return $recordedEvents;
77
    }
78
79
    private function reconstituteFromEvents(): AggregateRoot
80
    {
81
        $this->getStoredEventRepository()->retrieveAll($this->aggregateUuid)
82
            ->each(function (StoredEvent $storedEvent) {
83
                $this->apply($storedEvent->event);
84
            });
85
86
        return $this;
87
    }
88
89
    private function apply(ShouldBeStored $event): void
90
    {
91
        $classBaseName = class_basename($event);
92
93
        $camelCasedBaseName = ucfirst(Str::camel($classBaseName));
94
95
        $applyingMethodName = "apply{$camelCasedBaseName}";
96
97
        if (method_exists($this, $applyingMethodName)) {
98
            $this->$applyingMethodName($event);
99
        }
100
    }
101
102
    /**
103
     * @param \Spatie\EventSourcing\ShouldBeStored|\Spatie\EventSourcing\ShouldBeStored[] $events
104
     *
105
     * @return $this
106
     */
107
    public static function fake($events = []): FakeAggregateRoot
108
    {
109
        $events = Arr::wrap($events);
110
111
        return (new FakeAggregateRoot(app(static::class)))->given($events);
112
    }
113
}
114