Completed
Push — master ( 2c0599...af6fa8 )
by Freek
13s
created

StoredEvent::getEventClassAttribute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Spatie\EventProjector\Models;
4
5
use Exception;
6
use Carbon\Carbon;
7
use Illuminate\Support\Arr;
8
use Illuminate\Database\Eloquent\Model;
9
use Illuminate\Database\Eloquent\Builder;
10
use Spatie\EventProjector\ShouldBeStored;
11
use Spatie\EventProjector\Facades\Projectionist;
12
use Spatie\SchemalessAttributes\SchemalessAttributes;
13
use Spatie\EventProjector\Exceptions\InvalidStoredEvent;
14
use Spatie\EventProjector\EventSerializers\EventSerializer;
15
16
class StoredEvent extends Model
17
{
18
    public $guarded = [];
19
20
    public $timestamps = false;
21
22
    public $casts = [
23
        'event_properties' => 'array',
24
        'meta_data' => 'array',
25
    ];
26
27
    public static function createForEvent(ShouldBeStored $event, string $uuid = null): StoredEvent
28
    {
29
        $storedEvent = new static();
30
        $storedEvent->aggregate_uuid = $uuid;
31
        $storedEvent->event_class = static::getEventClass(get_class($event));
32
        $storedEvent->attributes['event_properties'] = app(EventSerializer::class)->serialize(clone $event);
33
        $storedEvent->meta_data = [];
34
        $storedEvent->created_at = Carbon::now();
35
36
        $storedEvent->save();
37
38
        return $storedEvent;
39
    }
40
41
    public function getEventClassAttribute(string $value): string
42
    {
43
        return static::getActualClassForEvent($value);
44
    }
45
46
    public function getEventAttribute(): ShouldBeStored
47
    {
48
        try {
49
            $event = app(EventSerializer::class)->deserialize(
50
                $this->event_class,
51
                $this->getOriginal('event_properties')
52
            );
53
        } catch (Exception $exception) {
54
            throw InvalidStoredEvent::couldNotUnserializeEvent($this, $exception);
55
        }
56
57
        return $event;
58
    }
59
60
    public function scopeStartingFrom(Builder $query, int $storedEventId): void
61
    {
62
        $query->where('id', '>=', $storedEventId);
63
    }
64
65
    public function scopeUuid(Builder $query, string $uuid): void
66
    {
67
        $query->where('aggregate_uuid', $uuid);
68
    }
69
70
    public function getMetaDataAttribute(): SchemalessAttributes
71
    {
72
        return SchemalessAttributes::createForModel($this, 'meta_data');
73
    }
74
75
    public function scopeWithMetaDataAttributes(): Builder
76
    {
77
        return SchemalessAttributes::scopeWithSchemalessAttributes('meta_data');
78
    }
79
80
    public static function storeMany(array $events, string $uuid = null): void
81
    {
82
        collect($events)
83
            ->map(function (ShouldBeStored $domainEvent) use ($uuid) {
84
                $storedEvent = static::createForEvent($domainEvent, $uuid);
85
86
                return [$domainEvent, $storedEvent];
87
            })
88
            ->eachSpread(function (ShouldBeStored $event, StoredEvent $storedEvent) {
89
                Projectionist::handleWithSyncProjectors($storedEvent);
90
91
                if (method_exists($event, 'tags')) {
92
                    $tags = $event->tags();
0 ignored issues
show
Bug introduced by
The method tags() does not seem to exist on object<Spatie\EventProjector\ShouldBeStored>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
93
                }
94
95
                $storedEventJob = call_user_func(
96
                    [config('event-projector.stored_event_job'), 'createForEvent'],
97
                    $storedEvent,
98
                    $tags ?? []
99
                );
100
101
                dispatch($storedEventJob->onQueue($event->queue ?? config('event-projector.queue')));
0 ignored issues
show
Bug introduced by
Accessing queue on the interface Spatie\EventProjector\ShouldBeStored suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
102
            });
103
    }
104
105
    public static function store(ShouldBeStored $event, string $uuid = null): void
106
    {
107
        static::storeMany([$event], $uuid);
108
    }
109
110
    protected static function getEventClass(string $class): string
111
    {
112
        $map = config('event-projector.event_class_map', []);
113
114
        if (! empty($map) && in_array($class, $map)) {
115
            return array_search($class, $map, true);
116
        }
117
118
        return $class;
119
    }
120
121
    protected static function getActualClassForEvent(string $class): string
122
    {
123
        return Arr::get(config('event-projector.event_class_map', []), $class, $class);
124
    }
125
}
126