*/ final readonly class ClientTicketProvider implements ProviderInterface { public function __construct( private EntityManagerInterface $entityManager, private Security $security, ) {} public function provide(Operation $operation, array $uriVariables = [], array $context = []): array|ClientTicket|null { $user = $this->security->getUser(); assert($user instanceof User); $repo = $this->entityManager->getRepository(ClientTicket::class); // Single item if (isset($uriVariables['id'])) { $ticket = $repo->find($uriVariables['id']); if (null === $ticket) { return null; } if (!$this->security->isGranted('ROLE_ADMIN') && $ticket->getSubmittedBy() !== $user) { return null; } return $ticket; } // Collection with manual filtering $qb = $repo->createQueryBuilder('ct') ->orderBy('ct.createdAt', 'DESC') ; // ROLE_CLIENT: only own tickets if (!$this->security->isGranted('ROLE_ADMIN')) { $qb->andWhere('ct.submittedBy = :user')->setParameter('user', $user); } // Apply filters from query parameters $filters = $context['filters'] ?? []; if (isset($filters['project'])) { $qb->andWhere('ct.project = :project') ->setParameter('project', self::extractId($filters['project'])) ; } if (isset($filters['status'])) { $qb->andWhere('ct.status = :status')->setParameter('status', $filters['status']); } if (isset($filters['submittedBy']) && $this->security->isGranted('ROLE_ADMIN')) { $qb->andWhere('ct.submittedBy = :submittedBy') ->setParameter('submittedBy', self::extractId($filters['submittedBy'])) ; } return $qb->getQuery()->getResult(); } /** * Extract an entity ID from a value that may be a numeric ID or an IRI string. */ private static function extractId(string $value): int { return is_numeric($value) ? (int) $value : (int) basename($value); } }