From 9b7dccac9d039802b1a0dd4f66756ec4a3691b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Wed, 2 Jul 2025 18:41:00 +0200 Subject: [PATCH] Add `TicketACLAwareRepository` with ACL-based ticket retrieval features - Implement `TicketACLAwareRepositoryInterface` for ticket queries with permission checks. - Add methods to find and count tickets based on parameters. - Include unit tests for repository functionality. --- .../Repository/TicketACLAwareRepository.php | 63 ++++++++++++++++++ .../TicketACLAwareRepositoryInterface.php | 37 +++++++++++ .../TicketACLAwareRepositoryTest.php | 66 +++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepository.php create mode 100644 src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepositoryInterface.php create mode 100644 src/Bundle/ChillTicketBundle/tests/Repository/TicketACLAwareRepositoryTest.php diff --git a/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepository.php b/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepository.php new file mode 100644 index 000000000..634f55214 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepository.php @@ -0,0 +1,63 @@ +buildQuery($params)->select('t')->getQuery()->setFirstResult($start) + ->setMaxResults($limit)->getResult(); + } + + public function countTickets(array $params): int + { + return $this->buildQuery($params)->select('COUNT(t)')->getQuery()->getSingleScalarResult(); + } + + private function buildQuery(array $params): QueryBuilder + { + $qb = $this->em->createQueryBuilder(); + $qb->from(Ticket::class, 't'); + // counter for all the loops + $i = 0; + + if (array_key_exists('byPerson', $params)) { + $or = $qb->expr()->orX(); + + foreach ($params['byPerson'] as $person) { + $or->add( + $qb->expr()->exists(sprintf( + 'SELECT 1 FROM %s tp_%d WHERE tp_%d.ticket = t AND tp_%d.person = :person_%d AND tp_%d.endDate IS NULL', + PersonHistory::class, + ++$i, + $i, + $i, + $i, + $i, + )) + ); + $qb->setParameter(sprintf('person_%d', $i), $person); + } + $qb->andWhere($or); + } + + return $qb; + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepositoryInterface.php b/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepositoryInterface.php new file mode 100644 index 000000000..e946c1ded --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Repository/TicketACLAwareRepositoryInterface.php @@ -0,0 +1,37 @@ +} $params + * + * @return list + */ + public function findTickets(array $params, int $start = 0, int $limit = 100): array; + + /** + * Find tickets. + * + * @param array{byPerson?: list} $params + */ + public function countTickets(array $params): int; +} diff --git a/src/Bundle/ChillTicketBundle/tests/Repository/TicketACLAwareRepositoryTest.php b/src/Bundle/ChillTicketBundle/tests/Repository/TicketACLAwareRepositoryTest.php new file mode 100644 index 000000000..4dac71bb1 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/tests/Repository/TicketACLAwareRepositoryTest.php @@ -0,0 +1,66 @@ +entityManager = self::getContainer()->get(EntityManagerInterface::class); + $this->repository = new TicketACLAwareRepository($this->entityManager); + } + + public function testFindNoParameters(): void + { + // Test the findTickets method with byPerson parameter + $actual = $this->repository->findTickets([]); + + // Only verify that the query executes successfully without checking results + self::assertIsList($actual); + } + + public function testFindTicketByPerson(): void + { + $person = $this->getRandomPerson($this->entityManager); + + // Test the findTickets method with byPerson parameter + $actual = $this->repository->findTickets(['byPerson' => [$person]]); + + // Only verify that the query executes successfully without checking results + self::assertIsList($actual); + } + + public function testCountTicketsByPerson(): void + { + $person = $this->getRandomPerson($this->entityManager); + + $result = $this->repository->countTickets(['byPerson' => [$person]]); + + self::assertIsInt($result); + } +}