$dto->user->getId(), 'token' => bin2hex(random_bytes(32)), 'available_to' => $dto->availableTo, ]); return $this->toDomain($model); } public function findByToken(string $token): ?EmailConfirmationToken { $model = EmailConfirmationTokenModel::where( 'token', $token, )->first(); return $model === null ? null : $this->toDomain($model); } public function findByUser(User $user): ?EmailConfirmationToken { $model = EmailConfirmationTokenModel::where( 'user_id', $user->getId(), )->first(); return $model === null ? null : $this->toDomain($model); } public function delete(int $id): void { EmailConfirmationTokenModel::query()->where('id', $id)->delete(); } private function toDomain( EmailConfirmationTokenModel $model, ): EmailConfirmationToken { $user = $this->userRepo->find($model->user_id); if ($user === null) { throw new DomainException( "User with id {$model->user_id} not found" ); } $availableTo = new DateTimeImmutable( $model->available_to->toDateTimeString(), new DateTimeZone('UTC'), ); return new EmailConfirmationToken( id: $model->id, user: $user, availableTo: $availableTo, token: $model->token, ); } }