*/ final readonly class ChangeStudentClassProcessor implements ProcessorInterface { public function __construct( private ChangeStudentClassHandler $handler, private ClassRepository $classRepository, private TenantContext $tenantContext, private MessageBusInterface $eventBus, private AuthorizationCheckerInterface $authorizationChecker, private CurrentAcademicYearResolver $academicYearResolver, ) { } /** * @param StudentResource $data */ #[Override] public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): StudentResource { if (!$this->authorizationChecker->isGranted(StudentVoter::MANAGE)) { throw new AccessDeniedHttpException('Vous n\'êtes pas autorisé à changer la classe d\'un élève.'); } if (!$this->tenantContext->hasTenant()) { throw new UnauthorizedHttpException('Bearer', 'Tenant non défini.'); } $tenantId = (string) $this->tenantContext->getCurrentTenantId(); /** @var string $studentId */ $studentId = $uriVariables['id'] ?? ''; $academicYearId = $this->academicYearResolver->resolve('current') ?? throw new BadRequestHttpException('Impossible de résoudre l\'année scolaire courante.'); try { $command = new ChangeStudentClassCommand( tenantId: $tenantId, studentId: $studentId, newClassId: $data->classId ?? '', academicYearId: $academicYearId, ); $assignment = ($this->handler)($command); // Dispatch domain events foreach ($assignment->pullDomainEvents() as $event) { $this->eventBus->dispatch($event); } // Update the resource with new class info $newClass = $this->classRepository->get($assignment->classId); $data->classId = (string) $assignment->classId; $data->className = (string) $newClass->name; $data->classLevel = $newClass->level?->value; return $data; } catch (ClasseNotFoundException $e) { throw new NotFoundHttpException($e->getMessage()); } } }