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 |
||
12 | use Spatie\SchemalessAttributes\SchemalessAttributes; |
||
13 | |||
14 | class StoredEvent implements Arrayable |
||
15 | { |
||
16 | public ?int $id; |
||
|
|||
17 | |||
18 | /** @var array|string */ |
||
19 | public $event_properties; |
||
20 | |||
21 | public string $aggregate_uuid; |
||
22 | |||
23 | public string $event_class; |
||
24 | |||
25 | public SchemalessAttributes $meta_data; |
||
26 | |||
27 | public string $created_at; |
||
28 | |||
29 | public ?ShouldBeStored $event; |
||
30 | |||
31 | public function __construct(array $data) |
||
32 | { |
||
33 | $this->id = $data['id'] ?? null; |
||
34 | $this->event_properties = $data['event_properties']; |
||
35 | $this->aggregate_uuid = $data['aggregate_uuid']; |
||
36 | $this->event_class = self::getActualClassForEvent($data['event_class']); |
||
37 | $this->meta_data = $data['meta_data']; |
||
38 | $this->created_at = $data['created_at']; |
||
39 | |||
40 | try { |
||
41 | $this->event = app(EventSerializer::class)->deserialize( |
||
42 | self::getActualClassForEvent($this->event_class), |
||
43 | is_string($this->event_properties) |
||
44 | ? $this->event_properties |
||
45 | : json_encode($this->event_properties) |
||
46 | ); |
||
47 | } catch (Exception $exception) { |
||
48 | throw InvalidStoredEvent::couldNotUnserializeEvent($this, $exception); |
||
49 | } |
||
50 | } |
||
51 | |||
52 | public function toArray() |
||
53 | { |
||
54 | return [ |
||
55 | 'id' => $this->id, |
||
56 | 'event_properties' => $this->event_properties, |
||
57 | 'aggregate_uuid' => $this->aggregate_uuid, |
||
58 | 'event_class' => self::getEventClass($this->event_class), |
||
59 | 'meta_data' => $this->meta_data instanceof Arrayable ? $this->meta_data->toArray() : (array) $this->meta_data, |
||
60 | 'created_at' => $this->created_at, |
||
61 | ]; |
||
62 | } |
||
63 | |||
64 | public function handle() |
||
65 | { |
||
66 | Projectionist::handleWithSyncProjectors($this); |
||
67 | |||
68 | if (method_exists($this->event, 'tags')) { |
||
69 | $tags = $this->event->tags(); |
||
70 | } |
||
71 | |||
72 | $storedEventJob = call_user_func( |
||
73 | [config('event-sourcing.stored_event_job'), 'createForEvent'], |
||
74 | $this, |
||
75 | $tags ?? [] |
||
76 | ); |
||
77 | |||
78 | dispatch($storedEventJob->onQueue($this->event->queue ?? config('event-sourcing.queue'))); |
||
79 | } |
||
80 | |||
81 | protected static function getActualClassForEvent(string $class): string |
||
82 | { |
||
83 | return Arr::get(config('event-sourcing.event_class_map', []), $class, $class); |
||
84 | } |
||
85 | |||
86 | protected static function getEventClass(string $class): string |
||
87 | { |
||
88 | $map = config('event-sourcing.event_class_map', []); |
||
89 | |||
90 | if (! empty($map) && in_array($class, $map)) { |
||
91 | return array_search($class, $map, true); |
||
92 | } |
||
93 | |||
94 | return $class; |
||
95 | } |
||
96 | } |
||
97 |