getNextId(); $user = new User( id: $id, email: $dto->email, displayName: $dto->displayName, passwordHash: $dto->passwordHash, isAdmin: $dto->isAdmin, emailConfirmedAt: $dto->emailConfirmedAt, ); $this->existingUsers[$id] = $user; return $this->copy($user); } public function find(int $id): ?User { $user = $this->existingUsers[$id] ?? null; if ($user === null) { return null; } return $this->copy($user); } public function findByEmail(EmailAddress $email): ?User { foreach ($this->existingUsers as $user) { if ($user->getEmail()->equals($email)) { return $this->copy($user); } } return null; } public function findByDisplayName(string $displayName): ?User { foreach ($this->existingUsers as $user) { if ($user->getDisplayName() === $displayName) { return $this->copy($user); } } return null; } /** * @return User[] */ public function search(string $query): array { $needle = strtolower($query); $results = []; foreach ($this->existingUsers as $user) { $displayName = strtolower($user->getDisplayName()); $email = strtolower($user->getEmail()->value()); if ( str_starts_with($displayName, $needle) || str_starts_with($email, $needle) ) { $results[] = $this->copy($user); } } usort( $results, function (User $left, User $right) { return strcmp( $left->getDisplayName(), $right->getDisplayName(), ); }, ); return $results; } /** * @throws RuntimeException */ public function update(User $user): User { $id = $user->getId(); if (! isset($this->existingUsers[$id])) { throw new RuntimeException( "User with id: $id does not exist" ); } $this->existingUsers[$id] = $user; return $this->copy($user); } private function copy(User $user): User { return new User( id: $user->getId(), email: $user->getEmail(), displayName: $user->getDisplayName(), passwordHash: $user->getPasswordHash(), isAdmin: $user->isAdmin(), emailConfirmedAt: $user->getEmailConfirmedAt(), ); } private function getNextId(): int { return count($this->existingUsers) + 1; } }