rolePolicy = $rolePolicy ?? new RolePolicy(); } /** @return User[] */ public function findAll(): array { return $this->userRepository->findAll(); } /** @return PaginatedResult */ public function findPaginated(int $page, int $perPage): PaginatedResult { $page = max(1, $page); $total = $this->userRepository->countAll(); $offset = ($page - 1) * $perPage; return new PaginatedResult( $this->userRepository->findPage($perPage, $offset), $total, $page, $perPage, ); } public function findById(int $id): ?User { return $this->userRepository->findById($id); } public function delete(int $id): void { $this->requireExistingUser($id); $this->userRepository->delete($id); } public function updateRole(int $id, string $role): void { $this->rolePolicy->assertAssignable($role); $this->requireExistingUser($id); $this->userRepository->updateRole($id, $role); } public function createUser(string $username, string $email, string $plainPassword, string $role = User::ROLE_USER): User { $username = mb_strtolower(trim($username)); $email = mb_strtolower(trim($email)); $plainPassword = trim($plainPassword); $this->rolePolicy->assertAssignable($role); if ($this->userRepository->findByUsername($username)) { throw new DuplicateUsernameException($username); } if ($this->userRepository->findByEmail($email)) { throw new DuplicateEmailException($email); } if (mb_strlen($plainPassword) < 8) { throw new WeakPasswordException(); } $passwordHash = password_hash($plainPassword, PASSWORD_BCRYPT, ['cost' => 12]); $user = new User(0, $username, $email, $passwordHash, $role); $this->userRepository->create($user); return $user; } private function requireExistingUser(int $id): User { $user = $this->userRepository->findById($id); if ($user === null) { throw new NotFoundException('Utilisateur', $id); } return $user; } }