111 lines
3.1 KiB
PHP
111 lines
3.1 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\User\Application;
|
|
|
|
use App\Shared\Exception\NotFoundException;
|
|
use App\Shared\Pagination\PaginatedResult;
|
|
use App\User\Domain\RolePolicy;
|
|
use App\User\Exception\DuplicateEmailException;
|
|
use App\User\Exception\DuplicateUsernameException;
|
|
use App\User\Exception\WeakPasswordException;
|
|
use App\User\User;
|
|
use App\User\UserRepositoryInterface;
|
|
use App\User\UserServiceInterface;
|
|
|
|
/**
|
|
* Service applicatif du domaine User.
|
|
*
|
|
* Gère la création des comptes, la pagination de l'administration et la mise à
|
|
* jour des rôles à partir de RolePolicy.
|
|
*/
|
|
class UserApplicationService implements UserServiceInterface
|
|
{
|
|
private readonly RolePolicy $rolePolicy;
|
|
|
|
public function __construct(
|
|
private readonly UserRepositoryInterface $userRepository,
|
|
?RolePolicy $rolePolicy = null,
|
|
) {
|
|
$this->rolePolicy = $rolePolicy ?? new RolePolicy();
|
|
}
|
|
|
|
/** @return User[] */
|
|
public function findAll(): array
|
|
{
|
|
return $this->userRepository->findAll();
|
|
}
|
|
|
|
/** @return PaginatedResult<User> */
|
|
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;
|
|
}
|
|
}
|