Completed
Push — master ( e000b3...b0a3db )
by Christopher
06:52 queued 48s
created

Aggregate::publish()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 5
rs 9.4286
ccs 4
cts 4
cp 1
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php namespace C4tech\RayEmitter\Domain;
2
3
use C4tech\RayEmitter\Contracts\Domain\Aggregate as AggregateInterface;
4
use C4tech\RayEmitter\Contracts\Domain\Command as CommandInterface;
5
use C4tech\RayEmitter\Contracts\Domain\Event as EventInterface;
6
use C4tech\RayEmitter\Contracts\Event\Collection as EventCollectionInterface;
7
use C4tech\RayEmitter\Exceptions\CommandHandlerMissing;
8
use C4tech\RayEmitter\Exceptions\EventHandlerMissing;
9
use C4tech\RayEmitter\Facades\EventStore;
10
use Illuminate\Support\Facades\Config;
11
12
abstract class Aggregate implements AggregateInterface
13
{
14
    /**
15
     * Aggregate root entity.
16
     * @var AggregateRootInterface
17
     */
18
    protected $root;
19
20
    /**
21
     * Event sequence counter.
22
     * @var integer
23
     */
24
    protected $sequence = 0;
25
26
    /**
27
     * Apply
28
     *
29
     * Alter the Aggregate Root's state by adding a single event.
30
     * @param  EventInterface $event An event that has occurred.
31
     * @return void
32
     */
33 2
    protected function apply(EventInterface $event)
34
    {
35 2
        $method = $this->createMethodName('apply', $event);
36
37 2
        if (!method_exists($this, $method)) {
38 1
            throw new EventHandlerMissing(
39 1
                sprintf(
40 1
                    'Command %s does not have a handler for its expected aggregate %s',
41 1
                    get_class($event),
42 1
                    get_class($this)
43 1
                ),
44
                501
45 1
            );
46
        }
47
48 1
        $this->$method($event);
49 1
    }
50
51
    /**
52
     * Create Method Name
53
     *
54
     * Generate a method name using a configurable prefix and an object's class basename.
55
     * @param  string $prefix_key     The key from the configuration to lookup the appropriate prefix.
56
     * @param  object $object         The object which shall be reduced to its class basename.
57
     * @param  string $prefix_default The default prefix.
58
     * @return string                 The method name to use.
59
     */
60 2
    protected function createMethodName($prefix_key, $object, $prefix_default = null)
61
    {
62 2
        if (!$prefix_default) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $prefix_default of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
63 1
            $prefix_default = $prefix_key;
64 1
            $prefix_key .= '_prefix';
65 1
        }
66
67 2
        $prefix = Config::get('ray_emitter.' . $prefix_key, $prefix_default);
68 2
        $base = class_basename($object);
69
70 2
        return $prefix . $base;
71
    }
72
73
    /**
74
     * @inheritDoc
75
     */
76 1
    public function getEntity()
77
    {
78 1
        return $this->root->makeEntity();
79
    }
80
81
    /**
82
     * @inheritDoc
83
     */
84 1
    public function getId()
85
    {
86 1
        return $this->root->getId();
87
    }
88
89
    /**
90
     * @inheritDoc
91
     */
92 3
    public function getSequence()
93
    {
94 3
        return $this->sequence;
95
    }
96
97
    /**
98
     * @inheritDoc
99
     */
100 2
    public function handle(CommandInterface $command)
101
    {
102 2
        $method = $this->createMethodName('handle', $command);
103
104 2
        if (!method_exists($this, $method)) {
105 1
            throw new CommandHandlerMissing(
106 1
                sprintf(
107 1
                    'Command %s does not have a handler for its expected aggregate %s',
108 1
                    get_class($command),
109 1
                    get_class($this)
110 1
                ),
111
                501
112 1
            );
113
        }
114
115 1
        $event = $this->$method($command);
116 1
        $this->publish($event);
117 1
    }
118
119
    /**
120
     * @inheritDoc
121
     */
122
    public function hydrate(EventCollectionInterface $events)
123
    {
124 1
        $events->each(function (EventInterface $event) {
125 1
            $this->apply($event);
126 1
            $this->sequence++;
127 1
        });
128 1
    }
129
130
    /**
131
     * Publish
132
     *
133
     * Adds a new event to the event queue, applies it to to the Aggregate Root's
134
     * state, and broadcasts the Event for listeners to handle.
135
     * @param  EventInterface $event An Event created by a Command handler.
136
     * @return void
137
     */
138 1
    protected function publish(EventInterface $event)
139
    {
140 1
        $this->apply($event);
141 1
        EventStore::enqueue($event);
142 1
    }
143
144
    /**
145
     * Magic Getter
146
     *
147
     * Expose getter methods on the Aggregate and Aggregate Root as properties.
148
     * @param  string $property Requested "property"
149
     * @return mixed
150
     */
151 2
    public function __get($property)
152
    {
153 2
        $method = 'get' . studly_case($property);
154
155 2
        if (method_exists($this, $method)) {
156 1
            return $this->$method();
157
        }
158
159 1
        return $this->root->$property;
160
    }
161
}
162