Passed
Push — master ( e55add...36a807 )
by Daniel
05:21
created

EventSourcedAggregateRoot::originalVersion()   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
namespace DDDominio\EventSourcing\Common;
4
5
abstract class EventSourcedAggregateRoot implements EventSourcedAggregateRootInterface
6
{
7
    /**
8
     * @var DomainEvent[]
9
     */
10
    private $changes = [];
11
12
    /**
13
     * @var int
14
     */
15
    private $version = 0;
16
17
    /**
18
     * @param mixed $domainEvent
19
     * @throws DomainEventNotUnderstandableException
20
     */
21 13
    public function applyAndRecord($domainEvent)
22
    {
23 13
        $domainEvent = $this->ensureDomainEvent($domainEvent);
24 13
        $this->apply($domainEvent);
25 13
        $this->record($domainEvent);
26 13
    }
27
28
    /**
29
     * @param mixed $domainEvent
30
     */
31 13
    private function record($domainEvent)
32
    {
33 13
        $this->changes[] = $domainEvent;
34 13
    }
35
36
    /**
37
     * @param mixed $domainEvent
38
     */
39 23
    public function apply($domainEvent)
40
    {
41 23
        $domainEvent = $this->ensureDomainEvent($domainEvent);
42 23
        $eventHandlerName = $this->getEventHandlerName($domainEvent);
43 23
        if (method_exists($this, $eventHandlerName)) {
44 22
            $this->executeEventHandler($this, $eventHandlerName, $domainEvent);
45
        } else {
46 3
            $this->applyRecursively($eventHandlerName, $domainEvent);
47
        }
48 22
    }
49
50
    /**
51
     * @param $domainEvent
52
     * @return DomainEvent
53
     */
54 23
    private function ensureDomainEvent($domainEvent)
55
    {
56 23
        if (!$domainEvent instanceof DomainEvent) {
57 23
            $domainEvent = DomainEvent::record($domainEvent);
58
        }
59 23
        return $domainEvent;
60
    }
61
62
    /**
63
     * @param string $eventHandlerName
64
     * @param mixed $domainEventData
65
     * @throws DomainEventNotUnderstandableException
66
     */
67 3
    private function applyRecursively($eventHandlerName, $domainEventData)
68
    {
69 3
        $applied = false;
70 3
        $reflectedClass = new \ReflectionClass(get_class($this));
71 3
        foreach ($reflectedClass->getProperties() as $property) {
72 3
            $propertyValue = $this->{$property->getName()};
73 3 View Code Duplication
            if (is_object($propertyValue)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
74 1
                if (method_exists($propertyValue, $eventHandlerName)) {
75 1
                    $this->executeEventHandler($propertyValue, $eventHandlerName, $domainEventData);
76 1
                    $applied = true;
77
                }
78
            }
79 3 View Code Duplication
            if (is_array($propertyValue)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
80 2
                foreach ($propertyValue as $item) {
81 1
                    if (method_exists($item, $eventHandlerName)) {
82 1
                        $this->executeEventHandler($item, $eventHandlerName, $domainEventData);
83 3
                        $applied = true;
84
                    }
85
                }
86
            }
87
        }
88 3
        if (!$applied) {
89 1
            throw DomainEventNotUnderstandableException::fromAggreagteAndEventTypes(
90
                get_class($this),
91
                get_class($domainEventData)
92
            );
93
        }
94 2
    }
95
96
    /**
97
     * @param DomainEvent $domainEvent
98
     * @return string
99
     */
100 23
    private function getEventHandlerName($domainEvent)
101
    {
102 23
        return 'when' . (new \ReflectionClass($domainEvent->data()))->getShortName();
103
    }
104
105
    /**
106
     * @param object $entity
107
     * @param string $eventHandlerName
108
     * @param DomainEvent $domainEvent
109
     */
110 22
    private function executeEventHandler($entity, $eventHandlerName, $domainEvent)
111
    {
112 22
        $entity->{$eventHandlerName}($domainEvent->data(), $domainEvent->occurredOn());
113 22
        $this->increaseAggregateVersion();
114 22
    }
115
116 22
    private function increaseAggregateVersion()
117
    {
118 22
        $this->version++;
119 22
    }
120
121
    /**
122
     * @return DomainEvent[]
123
     */
124 12
    public function changes()
125
    {
126 12
        return $this->changes;
127
    }
128
129
    /**
130
     * @return int
131
     */
132 8
    public function version()
133
    {
134 8
        return $this->version;
135
    }
136
137
    /**
138
     * @return int
139
     */
140 2
    public function originalVersion()
141
    {
142 2
        return $this->version - count($this->changes());
143
    }
144
145 7
    public function clearChanges()
146
    {
147 7
        $this->changes = [];
148 7
    }
149
}
150