Skip to content
Snippets Groups Projects
QuestRepository.php 5.61 KiB
Newer Older
i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
<?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 = [
i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
        'По возрастанию' => 'ASC',
        'По убыванию' => 'DESC'
i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
    ];
    public const SORT_FIELDS = [
i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
        'Название' => 'name',
        'Дата проведения' => 'date',
        'Дата финальной записи' => 'final_date'
i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
    ];

    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();
    }

i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
    public function findOneById(int $id, int $userId, bool $cache = true): ?Quest
i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
    {
        $queryBuilder = $this->getBaseQuery($userId);
        $queryBuilder->setParameter('detail_id', $id)
            ->andWhere('q.id = :detail_id');
i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
        $query = $queryBuilder->getQuery();
        if ($cache) {
            $query->enableResultCache(3600, $id);
        }
        return $query->getOneOrNullResult();
i.vasilenko@iq-adv.ru's avatar
i.vasilenko@iq-adv.ru committed
    }

    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()
    //        ;
    //    }
}