em = $entityManager; $this->repository = $entityManager->getRepository(CalendarRange::class); } public function countByAvailableRangesForUser(User $user, \DateTimeImmutable $from, \DateTimeImmutable $to): int { return $this->buildQueryAvailableRangesForUser($user, $from, $to) ->select('COUNT(cr)') ->getQuery()->getSingleScalarResult(); } public function find($id): ?CalendarRange { return $this->repository->find($id); } /** * @return array|CalendarRange[] */ public function findAll(): array { return $this->repository->findAll(); } /** * @return array|CalendarRange[] */ public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null) { return $this->repository->findBy($criteria, $orderBy, $limit, $offset); } /** * @return array|CalendarRange[] */ public function findByAvailableRangesForUser( User $user, \DateTimeImmutable $from, \DateTimeImmutable $to, ?int $limit = null, ?int $offset = null ): array { $qb = $this->buildQueryAvailableRangesForUser($user, $from, $to); if (null !== $limit) { $qb->setMaxResults($limit); } if (null !== $offset) { $qb->setFirstResult($offset); } return $qb->getQuery()->getResult(); } public function findOneBy(array $criteria): ?CalendarRange { return $this->repository->findOneBy($criteria); } public function getClassName(): string { return CalendarRange::class; } private function buildQueryAvailableRangesForUser(User $user, \DateTimeImmutable $from, \DateTimeImmutable $to): QueryBuilder { $qb = $this->repository->createQueryBuilder('cr'); return $qb ->where( $qb->expr()->andX( $qb->expr()->eq('cr.user', ':user'), $qb->expr()->gte('cr.startDate', ':startDate'), $qb->expr()->lte('cr.endDate', ':endDate'), $qb->expr()->eq(0, 'SIZE(cr.calendars)') ) ) ->setParameters([ 'user' => $user, 'startDate' => $from, 'endDate' => $to, ]); } /** * Given a list of remote ids, return an array where * keys are the remoteIds, and value is a boolean, true if the * id is present in database. * * @param array|list $remoteIds * @return array */ public function findRemoteIdsPresent(array $remoteIds): array { if (0 === count($remoteIds)) { return []; } $sql = "SELECT sq.remoteId as remoteid, EXISTS (SELECT 1 FROM chill_calendar.calendar_range cr WHERE cr.remoteId = sq.remoteId) AS present FROM ( VALUES %remoteIds% ) AS sq(remoteId); "; $remoteIdsStr = \implode( ', ', array_fill(0, count($remoteIds), '((?))') ); $rsm = new ResultSetMapping(); $rsm ->addScalarResult('remoteid', 'remoteId', Types::STRING) ->addScalarResult('present', 'present', Types::BOOLEAN); $rows = $this->em ->createNativeQuery( \strtr($sql, ['%remoteIds%' => $remoteIdsStr]), $rsm ) ->setParameters(array_values($remoteIds)) ->getResult(); $results = []; foreach ($rows as $r) { $results[$r['remoteId']] = $r['present']; } return $results; } }