em->createQueryBuilder(); $qb->from(Calendar::class, 'c'); $andX = $qb->expr()->andX($qb->expr()->eq('c.accompanyingPeriod', ':period')); $qb->setParameter('period', $period); if (null !== $startDate) { $andX->add($qb->expr()->gte('c.startDate', ':startDate')); $qb->setParameter('startDate', $startDate); } if (null !== $endDate) { $andX->add($qb->expr()->lte('c.endDate', ':endDate')); $qb->setParameter('endDate', $endDate); } $qb->where($andX); return $qb; } public function buildQueryByAccompanyingPeriodIgnoredByDates(AccompanyingPeriod $period, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate): QueryBuilder { $qb = $this->em->createQueryBuilder(); $qb->from(Calendar::class, 'c'); $andX = $qb->expr()->andX($qb->expr()->eq('c.accompanyingPeriod', ':period')); $qb->setParameter('period', $period); if (null !== $startDate) { $andX->add($qb->expr()->lt('c.startDate', ':startDate')); $qb->setParameter('startDate', $startDate); } if (null !== $endDate) { $andX->add($qb->expr()->gt('c.endDate', ':endDate')); $qb->setParameter('endDate', $endDate); } $qb->where($andX); return $qb; } /** * Base implementation. The list of allowed accompanying period is retrieved "manually" from @see{AccompanyingPeriodACLAwareRepository}. */ public function buildQueryByPerson(Person $person, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate): QueryBuilder { $qb = $this->em->createQueryBuilder() ->from(Calendar::class, 'c'); $this->addQueryByPersonWithoutDate($qb, $person); // filter by date if (null !== $startDate) { $qb->andWhere($qb->expr()->gte('c.startDate', ':startDate')) ->setParameter('startDate', $startDate); } if (null !== $endDate) { $qb->andWhere($qb->expr()->lte('c.endDate', ':endDate')) ->setParameter('endDate', $endDate); } return $qb; } /** * Base implementation. The list of allowed accompanying period is retrieved "manually" from @see{AccompanyingPeriodACLAwareRepository}. */ public function buildQueryByPersonIgnoredByDates(Person $person, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate): QueryBuilder { $qb = $this->em->createQueryBuilder() ->from(Calendar::class, 'c'); $this->addQueryByPersonWithoutDate($qb, $person); // filter by date if (null !== $startDate) { $qb->andWhere($qb->expr()->lt('c.startDate', ':startDate')) ->setParameter('startDate', $startDate); } if (null !== $endDate) { $qb->andWhere($qb->expr()->gt('c.endDate', ':endDate')) ->setParameter('endDate', $endDate); } return $qb; } public function countByAccompanyingPeriod(AccompanyingPeriod $period, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate): int { $qb = $this->buildQueryByAccompanyingPeriod($period, $startDate, $endDate)->select('count(c)'); return $qb->getQuery()->getSingleScalarResult(); } public function countByPerson(Person $person, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate): int { return $this->buildQueryByPerson($person, $startDate, $endDate) ->select('COUNT(c)') ->getQuery() ->getSingleScalarResult(); } public function countIgnoredByAccompanyingPeriod(AccompanyingPeriod $period, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate): int { $qb = $this->buildQueryByAccompanyingPeriodIgnoredByDates($period, $startDate, $endDate)->select('count(c)'); return $qb->getQuery()->getSingleScalarResult(); } public function countIgnoredByPerson(Person $person, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate): int { return $this->buildQueryByPersonIgnoredByDates($person, $startDate, $endDate) ->select('COUNT(c)') ->getQuery() ->getSingleScalarResult(); } /** * @return array|Calendar[] */ public function findByAccompanyingPeriod(AccompanyingPeriod $period, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate, ?array $orderBy = [], ?int $offset = null, ?int $limit = null): array { $qb = $this->buildQueryByAccompanyingPeriod($period, $startDate, $endDate)->select('c'); foreach ($orderBy as $sort => $order) { $qb->addOrderBy('c.' . $sort, $order); } if (null !== $offset) { $qb->setFirstResult($offset); } if (null !== $limit) { $qb->setMaxResults($limit); } return $qb->getQuery()->getResult(); } public function findByPerson(Person $person, ?DateTimeImmutable $startDate, ?DateTimeImmutable $endDate, ?array $orderBy = [], ?int $offset = null, ?int $limit = null): array { $qb = $this->buildQueryByPerson($person, $startDate, $endDate) ->select('c'); foreach ($orderBy as $sort => $order) { $qb->addOrderBy('c.' . $sort, $order); } if (null !== $offset) { $qb->setFirstResult($offset); } if (null !== $limit) { $qb->setMaxResults($limit); } return $qb->getQuery()->getResult(); } private function addQueryByPersonWithoutDate(QueryBuilder $qb, Person $person): void { // find the reachable accompanying periods for person $periods = $this->accompanyingPeriodACLAwareRepository->findByPerson($person, AccompanyingPeriodVoter::SEE); $qb ->where( $qb->expr()->orX( // the calendar where the person is the main person: $qb->expr()->eq('c.person', ':person'), // when the calendar is in a reachable period, and contains person $qb->expr()->andX( $qb->expr()->in('c.accompanyingPeriod', ':periods'), $qb->expr()->isMemberOf(':person', 'c.persons') ) ) ) ->setParameter('person', $person) ->setParameter('periods', $periods); } }