Completed
Push — master ( 23e886...768f8d )
by Julián
01:24
created

replayAggregateEventStream()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
/*
4
 * event-sourcing (https://github.com/phpgears/event-sourcing).
5
 * Event Sourcing base.
6
 *
7
 * @license MIT
8
 * @link https://github.com/phpgears/event-sourcing
9
 * @author Julián Gutiérrez <[email protected]>
10
 */
11
12
declare(strict_types=1);
13
14
namespace Gears\EventSourcing\Aggregate;
15
16
use Gears\Aggregate\EventBehaviour;
17
use Gears\EventSourcing\Aggregate\Exception\AggregateException;
18
use Gears\EventSourcing\Event\AggregateEvent;
19
use Gears\EventSourcing\Event\AggregateEventArrayStream;
20
use Gears\EventSourcing\Event\AggregateEventStream;
21
use Gears\Identity\Identity;
22
23
/**
24
 * Abstract aggregate root class.
25
 */
26
abstract class AbstractAggregateRoot implements AggregateRoot
27
{
28
    use AggregateBehaviour, EventBehaviour;
29
30
    /**
31
     * @var AggregateEvent[]
32
     */
33
    private $recordedAggregateEvents = [];
34
35
    /**
36
     * Prevent aggregate root direct instantiation.
37
     */
38
    final protected function __construct()
39
    {
40
        $this->version = 0;
41
    }
42
43
    /**
44
     * Set aggregate identity.
45
     *
46
     * @param Identity $identity
47
     */
48
    final protected function setIdentity(Identity $identity): void
49
    {
50
        $this->identity = $identity;
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56
    final public static function reconstituteFromEventStream(AggregateEventStream $eventStream): self
57
    {
58
        $instance = new static();
59
        $instance->replayAggregateEventStream($eventStream);
60
61
        return $instance;
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     *
67
     * @throws AggregateException
68
     */
69
    final public function replayAggregateEventStream(AggregateEventStream $eventStream): void
70
    {
71
        foreach ($eventStream as $event) {
72
            $this->version = $event->getAggregateVersion();
73
74
            $this->applyAggregateEvent($event);
75
        }
76
    }
77
78
    /**
79
     * Record aggregate event.
80
     *
81
     * @param AggregateEvent $event
82
     *
83
     * @throws AggregateException
84
     */
85
    final protected function recordAggregateEvent(AggregateEvent $event): void
86
    {
87
        $this->version++;
88
89
        $this->recordedAggregateEvents[] = $event->withAggregateVersion($this->version);
90
91
        $this->applyAggregateEvent($event);
92
    }
93
94
    /**
95
     * Apply aggregate event.
96
     *
97
     * @param AggregateEvent $event
98
     *
99
     * @throws AggregateException
100
     */
101
    final protected function applyAggregateEvent(AggregateEvent $event): void
102
    {
103
        $method = $this->getAggregateEventApplyMethodName($event);
104
105
        if (!\method_exists($this, $method)) {
106
            throw new AggregateException(\sprintf(
107
                'Aggregate event handling method %s for event %s does not exist',
108
                $method,
109
                \get_class($event)
110
            ));
111
        }
112
113
        $this->$method($event);
114
    }
115
116
    /**
117
     * Get event apply method name.
118
     *
119
     * @param AggregateEvent $event
120
     *
121
     * @return string
122
     */
123
    protected function getAggregateEventApplyMethodName(AggregateEvent $event): string
124
    {
125
        $classParts = \explode('\\', \get_class($event));
126
        /** @var string $className */
127
        $className = \end($classParts);
128
129
        return 'apply' . \str_replace(' ', '', \ucwords(\strtr($className, '_-', '  ')));
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135
    final public function getRecordedAggregateEvents(): AggregateEventStream
136
    {
137
        return new AggregateEventArrayStream($this->recordedAggregateEvents);
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143
    final public function clearRecordedAggregateEvents(): void
144
    {
145
        $this->recordedAggregateEvents = [];
146
    }
147
148
    /**
149
     * {@inheritdoc}
150
     */
151
    final public function collectRecordedAggregateEvents(): AggregateEventStream
152
    {
153
        $recordedEvents = new AggregateEventArrayStream($this->recordedAggregateEvents);
154
155
        $this->recordedAggregateEvents = [];
156
157
        return $recordedEvents;
158
    }
159
}
160