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 |