nextId(); $token = new EmailConfirmationToken( id: $id, user: $dto->user, availableTo: $dto->availableTo, token: bin2hex(random_bytes(32)), ); $this->existingTokens[$id] = $token; return $this->copy($token); } public function findByToken(string $token): ?EmailConfirmationToken { foreach ($this->existingTokens as $existing) { if ($existing->getToken() === $token) { return $this->copy($existing); } } return null; } public function findByUser(User $user): ?EmailConfirmationToken { foreach ($this->existingTokens as $existing) { if ($existing->getUser()->getId() === $user->getId()) { return $this->copy($existing); } } return null; } public function delete(int $id): void { unset($this->existingTokens[$id]); } private function copy( EmailConfirmationToken $token, ): EmailConfirmationToken { $user = $this->userRepo->find($token->getUser()->getId()) ?? $token->getUser(); return new EmailConfirmationToken( id: $token->getId(), user: $user, availableTo: $token->getAvailableTo(), token: $token->getToken(), ); } private function nextId(): int { return count($this->existingTokens) + 1; } }