*/ final readonly class StudentAveragesProvider implements ProviderInterface { public function __construct( private StudentAverageRepository $studentAverageRepository, private TenantContext $tenantContext, private Security $security, ) { } #[Override] public function provide(Operation $operation, array $uriVariables = [], array $context = []): StudentAveragesResource { if (!$this->tenantContext->hasTenant()) { throw new UnauthorizedHttpException('Bearer', 'Tenant non défini.'); } $user = $this->security->getUser(); if (!$user instanceof SecurityUser) { throw new UnauthorizedHttpException('Bearer', 'Authentification requise.'); } /** @var string $studentId */ $studentId = $uriVariables['studentId']; try { $userId = UserId::fromString($studentId); } catch (InvalidArgumentException) { throw new BadRequestHttpException('Identifiant d\'élève invalide.'); } // L'élève peut voir ses propres moyennes, les enseignants et admins aussi $isOwner = $user->userId() === $studentId; $isStaff = $this->hasAnyRole($user->getRoles(), [ Role::ADMIN->value, Role::PROF->value, Role::VIE_SCOLAIRE->value, ]); if (!$isOwner && !$isStaff) { throw new AccessDeniedHttpException('Accès non autorisé aux moyennes de cet élève.'); } $tenantId = $this->tenantContext->getCurrentTenantId(); /** @var array $filters */ $filters = $context['filters'] ?? []; /** @var string|null $periodId */ $periodId = $filters['periodId'] ?? null; $resource = new StudentAveragesResource(); $resource->studentId = $studentId; $resource->periodId = $periodId; if ($periodId === null) { return $resource; } $resource->subjectAverages = $this->studentAverageRepository->findDetailedSubjectAveragesForStudent( $userId, $periodId, $tenantId, ); $resource->generalAverage = $this->studentAverageRepository->findGeneralAverageForStudent( $userId, $periodId, $tenantId, ); return $resource; } /** * @param list $userRoles * @param list $allowedRoles */ private function hasAnyRole(array $userRoles, array $allowedRoles): bool { foreach ($userRoles as $role) { if (in_array($role, $allowedRoles, true)) { return true; } } return false; } }