Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/DefaultHeadersDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ class DefaultHeadersDecorator implements MessageDecorator
{
private ClassNameInflector $inflector;
private Clock|ClockInterface $clock;
/** @var non-empty-string */
private string $timeOfRecordingFormat;

/** @param non-empty-string $timeOfRecordingFormat */
public function __construct(
?ClassNameInflector $inflector = null,
null|Clock|ClockInterface $clock = null,
Expand Down
59 changes: 51 additions & 8 deletions src/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,29 @@

/**
* @template TId of AggregateRootId = AggregateRootId
* @template TPayload of object = object
*
* @phpstan-type HeaderValue int|string|array<mixed>|TId|null|bool|float
* @phpstan-type HeadersShape array<non-empty-string, HeaderValue>
*/
final class Message
{
public const TIME_OF_RECORDING_FORMAT = 'Y-m-d H:i:s.uO';

/**
* @param TPayload $payload
* @param HeadersShape $headers
*/
public function __construct(private object $payload, private array $headers = [])
{
}

/**
* @param non-empty-string $key
* @param HeaderValue $value
*
* @return Message<TId, TPayload>
*/
public function withHeader(string $key, int|string|array|AggregateRootId|null|bool|float $value): Message
{
$clone = clone $this;
Expand All @@ -26,6 +40,11 @@ public function withHeader(string $key, int|string|array|AggregateRootId|null|bo
return $clone;
}

/**
* @param HeadersShape $headers
*
* @return Message<TId, TPayload>
*/
public function withHeaders(array $headers): Message
{
$clone = clone $this;
Expand All @@ -34,6 +53,11 @@ public function withHeaders(array $headers): Message
return $clone;
}

/**
* @param non-empty-string $format
*
* @return Message<TId, TPayload>
*/
public function withTimeOfRecording(
DateTimeImmutable $timeOfRecording,
string $format = self::TIME_OF_RECORDING_FORMAT
Expand All @@ -47,6 +71,7 @@ public function withTimeOfRecording(
public function aggregateVersion(): int
{
$version = $this->headers[Header::AGGREGATE_ROOT_VERSION] ?? null;
\assert($version === null || \is_numeric($version));

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used \ on the calls, instead of importing the functions, to make it easier to simply remove these once PHPStan gets smarter 👍


if ($version === null) {
throw new RuntimeException("Can't get the version if the message has none.");
Expand All @@ -60,23 +85,28 @@ public function aggregateVersion(): int
*/
public function aggregateRootId(): ?AggregateRootId
{
return $this->headers[Header::AGGREGATE_ROOT_ID] ?? null;
$aggregateRootId = $this->headers[Header::AGGREGATE_ROOT_ID] ?? null;
\assert($aggregateRootId === null || $aggregateRootId instanceof AggregateRootId);

return $aggregateRootId;
}

public function aggregateRootType(): ?string
{
return $this->headers[Header::AGGREGATE_ROOT_TYPE] ?? null;
$aggregateRootType = $this->headers[Header::AGGREGATE_ROOT_TYPE] ?? null;
\assert($aggregateRootType === null || \is_string($aggregateRootType));

return $aggregateRootType;
}

public function timeOfRecording(): DateTimeImmutable
{
$format = $this->headers[Header::TIME_OF_RECORDING_FORMAT] ?? self::TIME_OF_RECORDING_FORMAT;
$header = $this->headers[Header::TIME_OF_RECORDING] ?? '';
\assert(\is_string($format));
\assert(\is_string($header));

/* @var DateTimeImmutable */
$timeOfRecording = DateTimeImmutable::createFromFormat(
'!' . $format,
$header = (string) ($this->headers[Header::TIME_OF_RECORDING] ?? '')
);
$timeOfRecording = \DateTimeImmutable::createFromFormat('!' . $format, $header);

if ( ! $timeOfRecording instanceof DateTimeImmutable) {
throw UnableToResolveTimeOfRecording::fromFormatAndHeader($format, $header);
Expand All @@ -85,23 +115,36 @@ public function timeOfRecording(): DateTimeImmutable
return $timeOfRecording;
}

public function header(string $key): int|string|array|AggregateRootId|null|bool|float
/**
* @param non-empty-string $key
*
* @return HeaderValue
*/
public function header(string $key): int|string|array|AggregateRootId|bool|float|null
{
return $this->headers[$key] ?? null;
}

/**
* @return HeadersShape
*/
public function headers(): array
{
return $this->headers;
}

/**
* @return TPayload
*/
public function payload(): object
{
return $this->payload;
}

/**
* @deprecated use ->payload instead
*
* @return TPayload
*/
public function event(): object
{
Expand Down