Permet aux administrateurs de créer, modifier et supprimer des classes pour organiser les élèves par niveau. L'archivage soft-delete préserve l'historique tout en masquant les classes obsolètes. Inclut la validation des noms (2-50 caractères), les niveaux scolaires du CP à la Terminale, et les contrôles d'accès par rôle.
82 lines
2.9 KiB
PHP
82 lines
2.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Administration\Infrastructure\Api\Processor;
|
|
|
|
use ApiPlatform\Metadata\Operation;
|
|
use ApiPlatform\State\ProcessorInterface;
|
|
use App\Administration\Application\Command\ArchiveClass\ArchiveClassCommand;
|
|
use App\Administration\Application\Command\ArchiveClass\ArchiveClassHandler;
|
|
use App\Administration\Domain\Exception\ClasseNonSupprimableException;
|
|
use App\Administration\Domain\Exception\ClasseNotFoundException;
|
|
use App\Administration\Domain\Model\SchoolClass\ClassId;
|
|
use App\Administration\Domain\Repository\ClassRepository;
|
|
use App\Administration\Infrastructure\Api\Resource\ClassResource;
|
|
use App\Administration\Infrastructure\Security\ClassVoter;
|
|
|
|
use function is_string;
|
|
|
|
use Override;
|
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
use Symfony\Component\Messenger\MessageBusInterface;
|
|
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
|
|
|
/**
|
|
* Processor API Platform pour supprimer (archiver) une classe.
|
|
*
|
|
* @implements ProcessorInterface<ClassResource, null>
|
|
*/
|
|
final readonly class DeleteClassProcessor implements ProcessorInterface
|
|
{
|
|
public function __construct(
|
|
private ArchiveClassHandler $handler,
|
|
private ClassRepository $classRepository,
|
|
private MessageBusInterface $eventBus,
|
|
private AuthorizationCheckerInterface $authorizationChecker,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @param ClassResource $data
|
|
*/
|
|
#[Override]
|
|
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): null
|
|
{
|
|
$classId = $uriVariables['id'] ?? null;
|
|
|
|
if (!is_string($classId)) {
|
|
throw new BadRequestHttpException('ID de classe manquant.');
|
|
}
|
|
|
|
// Vérifier les permissions avant toute action
|
|
$class = $this->classRepository->findById(ClassId::fromString($classId));
|
|
if ($class === null) {
|
|
throw new NotFoundHttpException('Classe introuvable.');
|
|
}
|
|
|
|
if (!$this->authorizationChecker->isGranted(ClassVoter::DELETE, $class)) {
|
|
throw new AccessDeniedHttpException('Vous n\'êtes pas autorisé à supprimer cette classe.');
|
|
}
|
|
|
|
try {
|
|
$command = new ArchiveClassCommand(classId: $classId);
|
|
|
|
$archivedClass = ($this->handler)($command);
|
|
|
|
// Dispatch domain events from the archived aggregate
|
|
foreach ($archivedClass->pullDomainEvents() as $event) {
|
|
$this->eventBus->dispatch($event);
|
|
}
|
|
|
|
return null;
|
|
} catch (ClasseNotFoundException) {
|
|
throw new NotFoundHttpException('Classe introuvable.');
|
|
} catch (ClasseNonSupprimableException $e) {
|
|
throw new BadRequestHttpException($e->getMessage());
|
|
}
|
|
}
|
|
}
|