<?php namespace App\Repository; use App\Entity\Quest; use App\Redis\RedisFilter; use App\Service\Dto\Classes\FilterDto; use DateInterval; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ManagerRegistry; /** * @extends ServiceEntityRepository<Quest> */ class QuestRepository extends ServiceEntityRepository { public const SORT_TYPES = [ 'ASC', 'DESC' ]; public const SORT_FIELDS = [ 'name', 'date', 'final_date' ]; public function __construct(ManagerRegistry $registry) { parent::__construct($registry, Quest::class); } public function findAllByFilter(int $userId): array { $queryBuilder = $this->getFilterQuery($userId); return $queryBuilder->getQuery()->getResult(); } public function findCompletedByFilter(int $userId): array { $queryBuilder = $this->getFilterQuery($userId); $currentDate = new \DateTime(); $queryBuilder->setParameter('current', $currentDate) ->andWhere('q.date < :current'); $queryBuilder->setParameter('user_id', $userId) ->leftJoin('q.appointments', 'appointments') ->andWhere('appointments.related_user = :user_id'); return $queryBuilder->getQuery()->getResult(); } public function findOneById(int $id, int $userId, bool $cache = true): ?Quest { $queryBuilder = $this->getBaseQuery($userId); $queryBuilder->setParameter('detail_id', $id) ->andWhere('q.id = :detail_id'); $query = $queryBuilder->getQuery(); if ($cache) { $query->enableResultCache(3600, $id); } return $query->getOneOrNullResult(); } private function getBaseQuery(int $userId): QueryBuilder { return $this->createQueryBuilder('q'); } private function getFilterQuery(int $userId): QueryBuilder { $queryBuilder = $this->getBaseQuery($userId); $redisFilter = new RedisFilter($userId); $filter = $redisFilter->get(); if ($filter instanceof FilterDto) { if (!empty($filter->search)) { $text = $filter->search; $queryBuilder->setParameter('search', "%$text%") ->orWhere('q.name LIKE :search') ->orWhere('q.short_description LIKE :search') ->orWhere('q.full_description LIKE :search'); } if ($genres = $filter->genres) { $queryBuilder->setParameter('genres', $genres) ->leftJoin('q.genre', 'genre') ->andWhere('genre.name IN (:genres)'); } if ($themes = $filter->themes) { $queryBuilder->setParameter('themes', $themes) ->leftJoin('q.theme', 'theme') ->andWhere('theme.name IN (:themes)'); } if ($tags = $filter->tags) { $queryBuilder->setParameter('tags', $tags) ->leftJoin('q.tags', 'tags') ->andWhere('tags.name IN (:tags)'); } if ($filter->sort && $filter->sortField && in_array($filter->sort, self::SORT_TYPES, true) && in_array($filter->sortField, self::SORT_FIELDS, true) ) { $queryBuilder->orderBy('q.'.$filter->sortField, $filter->sort); } } return $queryBuilder; } public function getStartQuests(): array { $queryBuilder = $this->createQueryBuilder('q'); $startDate = new \DateTime(); $startDate->setTime(0,0); $startDate->add(new DateInterval('P3D')); $endDate = new \DateTime(); $endDate->setTime(23,59, 59); $endDate->add(new DateInterval('P3D')); $queryBuilder->setParameter('start', $startDate) ->setParameter('end', $endDate) ->andWhere('q.date >= :start') ->andWhere('q.date <= :end'); return $queryBuilder->getQuery()->getResult(); } public function getEndQuests(): array { $queryBuilder = $this->createQueryBuilder('q'); $startDate = new \DateTime(); $startDate->setTime(0,0); $startDate->sub(new DateInterval('P1D')); $endDate = new \DateTime(); $endDate->setTime(23,59, 59); $endDate->sub(new DateInterval('P1D')); $queryBuilder->setParameter('start', $startDate) ->setParameter('end', $endDate) ->andWhere('q.date >= :start') ->andWhere('q.date <= :end'); return $queryBuilder->getQuery()->getResult(); } // /** // * @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() // ; // } }