/** * @param string $userId * @param string $name * @param string $password */ public function __construct($userId, $name, $password) { Assert::argumentNotEmpty($userId, 'User ID is required'); Assert::argumentNotEmpty($name, 'User name is required'); Assert::argumentNotEmpty($password, 'User password is required'); $this->apply(new UserRegistered($userId, $name, $password)); }
/** * @param string $streamName * @param int $streamVersion */ public function __construct($streamName, $streamVersion = 1) { Assert::argumentNotEmpty($streamName, 'Stream name is required'); Assert::argumentNotEmpty($streamVersion, 'Stream version is required'); $this->streamName = $streamName; $this->streamVersion = $streamVersion; }
/** * @param int $streamVersion * @param Event[] $events */ public function __construct($streamVersion, array $events) { Assert::argumentAtLeast($streamVersion, 1, 'Stream version must be 1 at least'); Assert::argumentLengthAtLeast($events, 1, 'Events list must NOT be empty'); $this->streamVersion = $streamVersion; array_walk($events, function (Event $event) { $this->events[] = $event; }); }
/** * @param Event[] $domainEvents * @param int $eventStreamVersion * @return $this */ public static function constructWithEventStream(array $domainEvents, $eventStreamVersion) { Assert::argumentAtLeast($eventStreamVersion, 1, 'Event version number must be at least 1'); $self = (new ReflectionClass(get_called_class()))->newInstanceWithoutConstructor(); foreach ($domainEvents as $domainEvent) { $self->mutateWhen($domainEvent); } $self->setUnmutatedVersion($eventStreamVersion); return $self; }
/** * @param string $eventClassName * @param string $serialization * @return Event * @throws EventSourcingException when failed to deserialize */ public function deserialize($eventClassName, $serialization) { Assert::argumentNotEmpty($eventClassName, 'Event class name is required'); Assert::argumentClassExists($eventClassName, 'Event class does not exist: %class%'); Assert::argumentSubclassOf($eventClassName, 'Goodby\\EventSourcing\\Event', 'Event class must be subclass of %parent%'); $data = json_decode($serialization, true); if (json_last_error() != JSON_ERROR_NONE) { throw EventSourcingException::failedToDeserializeEvent($this->getLastErrorMessage()); } /** @var $eventClassName Event */ return $eventClassName::fromContractualData($data); }
/** * @param object $entity * @param Event $domainEvent * @param string $mutatorMethodFormat * @throws EntityMutationException * @throws EntityMutationException */ public static function mutateWhen($entity, Event $domainEvent, $mutatorMethodFormat = 'when{EventClassName}') { Assert::argumentIsObject($entity, 'Entity must be an object'); $eventClassName = (new ReflectionClass($domainEvent))->getShortName(); $mutatorMethodName = str_replace('{EventClassName}', $eventClassName, $mutatorMethodFormat); if (method_exists($entity, $mutatorMethodName) === false) { throw EntityMutationException::mutatorMethodNotExist(get_class($entity), $mutatorMethodName, $domainEvent); } try { $mutatorMethod = new ReflectionMethod($entity, $mutatorMethodName); $mutatorMethod->setAccessible(true); $mutatorMethod->invoke($entity, $domainEvent); } catch (ReflectionException $because) { throw EntityMutationException::because($because); } }
/** * @param EventStreamId $eventStreamId * @param Event[] $events * @throws * @return void */ public function append(EventStreamId $eventStreamId, array $events) { Assert::argumentLengthAtLeast($events, 1, 'At least one event is required'); try { $this->connection->beginTransaction(); $statement = $this->connection->prepare(sprintf('INSERT INTO `%s` (stream_name, stream_version, event_type, event_body) ' . 'VALUES (:stream_name, :stream_version, :event_type, :event_body)', $this->tableName)); $streamIndex = 0; foreach ($events as $event) { $this->appendEvent($statement, $eventStreamId->streamName(), $eventStreamId->streamVersion() + $streamIndex, $event); $streamIndex += 1; } $this->connection->commit(); } catch (Exception $because) { $this->connection->rollBack(); throw EventSourcingException::failedToAppend($because); } if ($this->notifiable) { $this->notifiable->notifyEvents(); } }
/** * @param string $eventId * @param Event $event */ public function __construct($eventId, Event $event) { Assert::argumentNotEmpty($eventId, 'Event ID is required'); $this->eventId = $eventId; $this->event = $event; }