AbstractEventSourcedAggregateRoot   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 89
Duplicated Lines 16.85 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 59.52%

Importance

Changes 10
Bugs 2 Features 0
Metric Value
wmc 13
c 10
b 2
f 0
lcom 1
cbo 6
dl 15
loc 89
ccs 25
cts 42
cp 0.5952
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A initializeState() 0 16 3
getChildEntities() 0 1 ?
handle() 0 1 ?
B apply() 0 24 5
A handleRecursively() 15 15 4
A getVersion() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/*
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * The software is based on the Axon Framework project which is
17
 * licensed under the Apache 2.0 license. For more information on the Axon Framework
18
 * see <http://www.axonframework.org/>.
19
 * 
20
 * This software consists of voluntary contributions made by many individuals
21
 * and is licensed under the MIT license. For more information, see
22
 * <http://www.governor-framework.org/>.
23
 */
24
25
namespace Governor\Framework\EventSourcing;
26
27
use Governor\Framework\Domain\MetaData;
28
use Governor\Framework\Domain\GenericDomainEventMessage;
29
use Governor\Framework\Domain\DomainEventMessageInterface;
30
use Governor\Framework\Domain\DomainEventStreamInterface;
31
use Governor\Framework\Domain\AbstractAggregateRoot;
32
33
/**
34
 * Abstract implementation of the {@see EventSourcedAggregateRootInterface} to be used as a base class for event sourced aggregates.
35
 *
36
 * @author    "David Kalosi" <[email protected]>
37
 * @license   <a href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>
38
 */
39
abstract class AbstractEventSourcedAggregateRoot extends AbstractAggregateRoot implements EventSourcedAggregateRootInterface
40
{
41
42
    /**
43
     * {@inheritdoc}
44
     */
45 10
    public function initializeState(DomainEventStreamInterface $domainEventStream)
46
    {
47 10
        if (0 !== $this->getUncommittedEventCount()) {
48
            throw new \RuntimeException("Aggregate is already initialized");
49
        }
50
51 10
        $lastScn = -1;
52
53 10
        while ($domainEventStream->hasNext()) {
54 10
            $event = $domainEventStream->next();
55 10
            $lastScn = $event->getScn();
56 10
            $this->handleRecursively($event);
57 10
        }
58
59 10
        $this->initializeEventStream($lastScn);
60 10
    }
61
62
    /**
63
     * @return EventSourcedEntityInterface[]
64
     */
65
    abstract protected function getChildEntities();
66
67
    /**
68
     * @param DomainEventMessageInterface $event
69
     * @return mixed
70
     */
71
    abstract protected function handle(DomainEventMessageInterface $event);
72
73
    /**
74
     * @param mixed $payload
75
     * @param MetaData $metaData
76
     */
77 36
    public function apply($payload, MetaData $metaData = null)
78
    {
79 36
        $metaData = isset($metaData) ? $metaData : MetaData::emptyInstance();
80
81 36
        if (null === $this->getIdentifier()) {
82
            if ($this->getUncommittedEventCount() > 0 || $this->getVersion() !== null) {
83
                throw new \RuntimeException(
84
                    "The Aggregate Identifier has not been initialized. "
85
                    ."It must be initialized at the latest when the "
86
                    ."first event is applied."
87
                );
88
            }
89
            $this->handleRecursively(
90
                new GenericDomainEventMessage(
91
                    null, 0,
92
                    $payload, $metaData
93
                )
94
            );
95
            $this->registerEvent($payload, $metaData);
96
        } else {
97 36
            $event = $this->registerEvent($payload, $metaData);
98 36
            $this->handleRecursively($event);
99
        }
100 36
    }
101
102 39 View Code Duplication
    private function handleRecursively(DomainEventMessageInterface $event)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
103
    {
104 39
        $this->handle($event);
105
106 39
        if (null === $childEntities = $this->getChildEntities()) {
107 13
            return;
108
        }
109
110 26
        foreach ($childEntities as $child) {
111
            if (null !== $child) {
112
                $child->registerAggregateRoot($this);
113
                $child->handleRecursively($event);
114
            }
115 26
        }
116 26
    }
117
118
119
    /**
120
     * @return int
121
     */
122 19
    public function getVersion()
123
    {
124 19
        return $this->getLastCommittedEventScn();
125
    }
126
127
}
128