Skip to content

Commit

Permalink
Merge branch 'release/4.3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
matiux committed Jun 5, 2023
2 parents 0ab071c + 4ea1a46 commit fdf766c
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 32 deletions.
60 changes: 50 additions & 10 deletions src/Matiux/DDDStarterPack/Event/DomainEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,25 @@
namespace DDDStarterPack\Event;

use DDDStarterPack\Identity\AggregateId;
use DDDStarterPack\Identity\Trace\CausationId;
use DDDStarterPack\Identity\Trace\CorrelationId;
use DDDStarterPack\Identity\Trace\DomainTrace;
use DDDStarterPack\Type\DateTimeRFC;

/**
* @template I of AggregateId
* @template-covariant I of AggregateId
*
* @psalm-type SerializedDomainEvent = array{
* event_name: string,
* aggregate_id: string,
* event_payload: array,
* occurred_at: string,
* meta: array{
* event_id: string,
* event_version: int,
* domain_trace: array{correlation_id: string, causation_id: string}
* }
* }
*/
abstract readonly class DomainEvent
{
Expand All @@ -19,11 +33,9 @@
* @param I $aggregateId
*/
protected function __construct(
public EventId $eventId,
public mixed $aggregateId,
public DomainTrace $domainTrace,
public DomainEventVersion $version,
public DateTimeRFC $occurredAt,
public DomainEventMeta $meta,
) {
$this->eventName = strtolower(
preg_replace(
Expand All @@ -34,22 +46,50 @@ protected function __construct(
);
}

/** @return SerializedDomainEvent */
public function serialize(): array
{
return [
'event_id' => $this->eventId->value(),
'event_name' => $this->eventName,
'aggregate_id' => $this->aggregateId->value(),
'event_payload' => $this->serializeEventPayload(),
'event_version' => $this->version->v,
'domain_trace' => [
'correlation_id' => $this->domainTrace->correlationId->value(),
'causation_id' => $this->domainTrace->causationId->value(),
],
'occurred_at' => $this->occurredAt->value(),
'meta' => [
'event_id' => $this->meta->eventId->value(),
'event_version' => $this->meta->version->v,
'domain_trace' => [
'correlation_id' => $this->meta->domainTrace->correlationId->value(),
'causation_id' => $this->meta->domainTrace->causationId->value(),
],
],
];
}

protected static function deserializeMeta(array $meta): DomainEventMeta
{
/** @var string[] $domainTrace */
$domainTrace = $meta['domain_trace'];

return new DomainEventMeta(
EventId::from((string) $meta['event_id']),
DomainTrace::fromIds(
CorrelationId::from($domainTrace['correlation_id']),
CausationId::from($domainTrace['causation_id']),
),
new DomainEventVersion((int) $meta['event_version']),
);
}

abstract protected function serializeEventPayload(): array;

abstract public function enrich(EnrichOptions $enrichOptions): self;

protected function enrichedDomainEventMeta(EnrichOptions $enrichOptions): DomainEventMeta
{
return new DomainEventMeta(
$enrichOptions->eventId ?? $this->meta->eventId,
$enrichOptions->domainTrace,
$this->meta->version,
);
}
}
27 changes: 27 additions & 0 deletions src/Matiux/DDDStarterPack/Event/DomainEventMeta.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace DDDStarterPack\Event;

use DDDStarterPack\Identity\Trace\DomainTrace;

final readonly class DomainEventMeta
{
public function __construct(
public EventId $eventId,
public DomainTrace $domainTrace,
public DomainEventVersion $version,
) {
}

public function toArray(): array
{
return [
'event_id' => $this->eventId->value(),
'correlation_id' => $this->domainTrace->correlationId->value(),
'causation_id' => $this->domainTrace->causationId->value(),
'event_version' => $this->version->v,
];
}
}
6 changes: 4 additions & 2 deletions src/Matiux/DDDStarterPack/Event/EnrichOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

readonly class EnrichOptions
{
public function __construct(public DomainTrace $domainTrace)
{
public function __construct(
public DomainTrace $domainTrace,
public null|EventId $eventId = null,
) {
}
}
4 changes: 2 additions & 2 deletions src/Matiux/DDDStarterPack/Event/EventId.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

namespace DDDStarterPack\Event;

use DDDStarterPack\Identity\AggregateId;
use DDDStarterPack\Identity\UuidV4;

readonly class EventId extends AggregateId
readonly class EventId extends UuidV4
{
}
23 changes: 23 additions & 0 deletions src/Matiux/DDDStarterPack/Event/Test/EventTestUtil.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace DDDStarterPack\Event\Test;

trait EventTestUtil
{
public static function assertIsDomainEventSerialized(array $serialized): void
{
self::assertArrayHasKey('aggregate_id', $serialized);
self::assertArrayHasKey('occurred_at', $serialized);
self::assertArrayHasKey('event_payload', $serialized);

self::assertArrayHasKey('meta', $serialized);

$meta = $serialized['meta'];

self::assertArrayHasKey('event_id', $meta);
self::assertArrayHasKey('event_version', $meta);
self::assertArrayHasKey('domain_trace', $meta);
}
}
10 changes: 9 additions & 1 deletion src/Matiux/DDDStarterPack/Identity/BasicGenericId.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*
* @implements GenericId<T>
*/
abstract readonly class BasicGenericId implements GenericId
abstract readonly class BasicGenericId implements GenericId, \JsonSerializable
{
/**
* @param T $id
Expand All @@ -35,4 +35,12 @@ public function __toString(): string
{
return (string) $this->value();
}

/**
* @return T
*/
public function jsonSerialize(): mixed
{
return $this->id;
}
}
37 changes: 37 additions & 0 deletions tests/Unit/DDDStarterPack/Event/DomainEventMetaTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Tests\Unit\DDDStarterPack\Event;

use DDDStarterPack\Event\DomainEventMeta;
use DDDStarterPack\Event\DomainEventVersion;
use DDDStarterPack\Event\EventId;
use DDDStarterPack\Identity\Trace\DomainTrace;
use PHPUnit\Framework\TestCase;

class DomainEventMetaTest extends TestCase
{
/**
* @test
*/
public function it_should_encode(): void
{
$eventId = EventId::new();
$domainTrace = DomainTrace::init($eventId);
$v = new DomainEventVersion(1);

$meta = new DomainEventMeta($eventId, $domainTrace, $v);

$expected = [
'event_id' => $eventId->value(),
'correlation_id' => $eventId->value(),
'causation_id' => $eventId->value(),
'event_version' => 1,
];

$encoded = $meta->toArray();

self::assertEquals($expected, $encoded);
}
}
63 changes: 46 additions & 17 deletions tests/Unit/DDDStarterPack/Event/DomainEventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Tests\Unit\DDDStarterPack\Event;

use DDDStarterPack\Event\DomainEvent;
use DDDStarterPack\Event\DomainEventMeta;
use DDDStarterPack\Event\DomainEventVersion;
use DDDStarterPack\Event\EnrichOptions;
use DDDStarterPack\Event\EventId;
Expand All @@ -22,9 +23,7 @@ class DomainEventTest extends TestCase
*/
public function it_shoud_serialize_event(): void
{
$eventId = EventId::new();
$aggregateId = AggregateId::new();
$domainTrace = DomainTrace::init($eventId);
$occurredAt = new DateTimeRFC();

$event = SomethingHappened::crea(
Expand All @@ -50,48 +49,79 @@ public function it_shoud_serialize_event(): void

$serialized = $event->serialize();
self::assertArrayHasKey('event_payload', $serialized);
self::assertArrayHasKey('domain_trace', $serialized);
self::assertArrayHasKey('meta', $serialized);

$meta = $serialized['meta'];

self::assertEquals($expectedEventPayload, $serialized['event_payload']);
self::assertEquals($expectedDomainTrace, $serialized['domain_trace']);
self::assertEquals($expectedDomainTrace, $meta['domain_trace']);
self::assertEquals('something_happened', $event->eventName);
}

/**
* @test
*/
public function it_should_deserialize(): void
{
$aggregateId = AggregateId::new();
$occurredAt = new DateTimeRFC();

$serializedEvent = SomethingHappened::crea(
$aggregateId,
$occurredAt,
'Matiux',
)->serialize();

$event = SomethingHappened::deserialize($serializedEvent);

self::assertTrue($event->aggregateId->equals($aggregateId));
self::assertEquals($occurredAt, $event->occurredAt);
}
}

/**
* @psalm-import-type SerializedDomainEvent from DomainEvent
*
* @extends DomainEvent<AggregateId>
*/
readonly class SomethingHappened extends DomainEvent
{
protected function __construct(
EventId $eventId,
AggregateId $aggregateId,
DomainTrace $domainTrace,
DateTimeRFC $occurredAt,
DomainEventMeta $domainEventMeta,
public string $name,
) {
parent::__construct(
$eventId,
$aggregateId,
$domainTrace,
new DomainEventVersion(1),
$occurredAt,
);
parent::__construct($aggregateId, $occurredAt, $domainEventMeta);
}

public static function crea(AggregateId $aggregateId, DateTimeRFC $occurredAt, string $name): self
{
$eventId = EventId::new();

return new self(
$eventId,
$aggregateId,
DomainTrace::init($eventId),
$occurredAt,
new DomainEventMeta($eventId, DomainTrace::init($eventId), new DomainEventVersion(1)),
$name,
);
}

/**
* @param SerializedDomainEvent $data
*
* @throws \Exception
*/
public static function deserialize(array $data): self
{
return new self(
AggregateId::from($data['aggregate_id']),
DateTimeRFC::createFrom($data['occurred_at']),
self::deserializeMeta($data['meta']),
(string) $data['event_payload']['name'],
);
}

protected function serializeEventPayload(): array
{
return [
Expand All @@ -102,10 +132,9 @@ protected function serializeEventPayload(): array
public function enrich(EnrichOptions $enrichOptions): self
{
return new self(
$this->eventId,
$this->aggregateId,
$enrichOptions->domainTrace,
$this->occurredAt,
$this->enrichedDomainEventMeta($enrichOptions),
$this->name,
);
}
Expand Down

0 comments on commit fdf766c

Please sign in to comment.