<?php namespace App\Repository; use App\Entity\Quest; use App\Redis\RedisFilter; use App\Service\Dto\Classes\FilterDto; use App\Service\Response\Classes\Data\Pagination; use DateInterval; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\Query\QueryException; use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\Tools\Pagination\Paginator; use Doctrine\Persistence\ManagerRegistry; /** * @extends ServiceEntityRepository<Quest> */ class QuestRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, Quest::class); } /** * Получение всех квестов по фильтру * * @param int $userId * * @return array */ public function findAllByFilter(int $userId): array { $queryBuilder = $this->getFilterQuery($userId); return $queryBuilder->getQuery()->getResult(); } /** * Получение всех квестов по фильтру постранично * * @param int $userId * @param int $page * @param int $limit * * @return Pagination */ public function findAllByFilterPaged(int $userId, int $page = 1, int $limit = 10): Pagination { $queryBuilder = $this->getFilterQuery($userId); $paginator = new Paginator($queryBuilder->getQuery()); $result = new Pagination(); $maxCount = count($paginator); $maxPage = ceil($maxCount / $limit); if ($page > $maxPage) { $page = (int)$maxPage; } if ($page > 0) { $result->page = $page; $result->maxPage = $maxPage; $result->limit = $limit; $paginator->getQuery() ->setFirstResult(($page - 1) * $limit) ->setMaxResults($limit); } $result->quests = $paginator->getQuery()->getResult(); return $result; } /** * Получение пройденных квестов * * @param int $userId * * @return array * * @throws QueryException */ public function findCompletedByFilter(int $userId): array { $queryBuilder = $this->getBaseQuery(); $criteria = Criteria::create(); $expr = Criteria::expr(); if (!$expr) { return []; } $currentDate = new \DateTime(); $criteria ->andWhere($expr->lt('date', $currentDate)) ->andWhere($expr->eq('appointments.related_user', $userId)); $queryBuilder->addCriteria($criteria); return $queryBuilder->getQuery()->getResult(); } /** * Получение квеста * * @param int $id * @param int $userId * @param bool $cache * * @return Quest|null */ public function findOneById(int $id, int $userId, bool $cache = true): ?Quest { $queryBuilder = $this->getBaseQuery(); $queryBuilder->setParameter('detail_id', $id) ->andWhere('q.id = :detail_id'); $query = $queryBuilder->getQuery(); if ($cache) { $query->enableResultCache(3600, $id); } return $query->getOneOrNullResult(); } /** * Получение квестов по критерии * * @param Criteria $criteria * * @return array */ public function getByCriteria(Criteria $criteria): array { return $this->getQueryByCriteria($criteria)->getQuery()->getResult(); } private function getBaseQuery(): QueryBuilder { return $this->createQueryBuilder('q') ->leftJoin('q.genre', 'genre') ->leftJoin('q.theme', 'theme') ->leftJoin('q.tags', 'tags') ->leftJoin('q.appointments', 'appointments') ->leftJoin('q.reviews', 'reviews'); } private function getQueryByCriteria(Criteria $criteria): QueryBuilder { $queryBuilder = $this->getBaseQuery(); $queryBuilder->addCriteria($criteria); return $queryBuilder; } private function getFilterQuery(int $userId): QueryBuilder { $redisFilter = new RedisFilter($userId); $filter = $redisFilter->get(); if ($filter instanceof FilterDto) { $criteria = $filter->getCriteria(); $queryBuilder = $this->getQueryByCriteria($criteria); } else { $queryBuilder = $this->getBaseQuery(); } return $queryBuilder; } // /** // * @return Quest[] Returns an array of Quest objects // */ // public function findByExampleField($value): array // { // return $this->createQueryBuilder('q') // ->andWhere('q.exampleField = :val') // ->setParameter('val', $value) // ->orderBy('q.id', 'ASC') // ->setMaxResults(10) // ->getQuery() // ->getResult() // ; // } // public function findOneBySomeField($value): ?Quest // { // return $this->createQueryBuilder('q') // ->andWhere('q.exampleField = :val') // ->setParameter('val', $value) // ->getQuery() // ->getOneOrNullResult() // ; // } }