Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • i.vasilenko/symfony-trainee
1 result
Show changes
Commits on Source (2)
...@@ -5,6 +5,8 @@ namespace App\Messenger\Handler; ...@@ -5,6 +5,8 @@ namespace App\Messenger\Handler;
use App\Entity\Quest; use App\Entity\Quest;
use App\Messenger\Message\QuestMessage; use App\Messenger\Message\QuestMessage;
use App\Messenger\Objects\QuestsEnd; use App\Messenger\Objects\QuestsEnd;
use DateInterval;
use Doctrine\Common\Collections\Criteria;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\MessageBusInterface;
...@@ -29,7 +31,7 @@ class QuestEndMessageHandler ...@@ -29,7 +31,7 @@ class QuestEndMessageHandler
*/ */
public function __invoke(QuestsEnd $message): void public function __invoke(QuestsEnd $message): void
{ {
$quests = $this->doctrine->getRepository(Quest::class)->getEndQuests(); $quests = $this->doctrine->getRepository(Quest::class)->getByCriteria($this->getCriteria());
foreach ($quests as $quest) { foreach ($quests as $quest) {
$appointments = $quest->getAppointments(); $appointments = $quest->getAppointments();
...@@ -59,4 +61,32 @@ class QuestEndMessageHandler ...@@ -59,4 +61,32 @@ class QuestEndMessageHandler
} }
} }
} }
/**
* Фильтр квестов
*
* @return Criteria
*/
public function getCriteria(): Criteria
{
$criteria = Criteria::create();
$expr = Criteria::expr();
if (!$expr) {
return $criteria;
}
$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'));
$criteria
->andWhere($expr->gte('date', $startDate))
->andWhere($expr->lte('date', $endDate));
return $criteria;
}
} }
\ No newline at end of file
...@@ -5,6 +5,8 @@ namespace App\Messenger\Handler; ...@@ -5,6 +5,8 @@ namespace App\Messenger\Handler;
use App\Entity\Quest; use App\Entity\Quest;
use App\Messenger\Message\QuestMessage; use App\Messenger\Message\QuestMessage;
use App\Messenger\Objects\QuestsStart; use App\Messenger\Objects\QuestsStart;
use DateInterval;
use Doctrine\Common\Collections\Criteria;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Messenger\Attribute\AsMessageHandler; use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Messenger\MessageBusInterface;
...@@ -29,7 +31,7 @@ class QuestStartMessageHandler ...@@ -29,7 +31,7 @@ class QuestStartMessageHandler
*/ */
public function __invoke(QuestsStart $message): void public function __invoke(QuestsStart $message): void
{ {
$quests = $this->doctrine->getRepository(Quest::class)->getStartQuests(); $quests = $this->doctrine->getRepository(Quest::class)->getByCriteria($this->getCriteria());
foreach ($quests as $quest) { foreach ($quests as $quest) {
$appointments = $quest->getAppointments(); $appointments = $quest->getAppointments();
...@@ -59,4 +61,32 @@ class QuestStartMessageHandler ...@@ -59,4 +61,32 @@ class QuestStartMessageHandler
} }
} }
} }
/**
* Фильтр квестов
*
* @return Criteria
*/
public function getCriteria(): Criteria
{
$criteria = Criteria::create();
$expr = Criteria::expr();
if (!$expr) {
return $criteria;
}
$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'));
$criteria
->andWhere($expr->gte('date', $startDate))
->andWhere($expr->lte('date', $endDate));
return $criteria;
}
} }
\ No newline at end of file
...@@ -8,6 +8,8 @@ use App\Service\Dto\Classes\FilterDto; ...@@ -8,6 +8,8 @@ use App\Service\Dto\Classes\FilterDto;
use App\Service\Response\Classes\Data\Pagination; use App\Service\Response\Classes\Data\Pagination;
use DateInterval; use DateInterval;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\Query\QueryException;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator; use Doctrine\ORM\Tools\Pagination\Paginator;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
...@@ -17,27 +19,33 @@ use Doctrine\Persistence\ManagerRegistry; ...@@ -17,27 +19,33 @@ use Doctrine\Persistence\ManagerRegistry;
*/ */
class QuestRepository extends ServiceEntityRepository class QuestRepository extends ServiceEntityRepository
{ {
public const SORT_TYPES = [
'По возрастанию' => 'ASC',
'По убыванию' => 'DESC'
];
public const SORT_FIELDS = [
'Название' => 'name',
'Дата проведения' => 'date',
'Дата финальной записи' => 'final_date'
];
public function __construct(ManagerRegistry $registry) public function __construct(ManagerRegistry $registry)
{ {
parent::__construct($registry, Quest::class); parent::__construct($registry, Quest::class);
} }
/**
* Получение всех квестов по фильтру
*
* @param int $userId
*
* @return array
*/
public function findAllByFilter(int $userId): array public function findAllByFilter(int $userId): array
{ {
$queryBuilder = $this->getFilterQuery($userId); $queryBuilder = $this->getFilterQuery($userId);
return $queryBuilder->getQuery()->getResult(); 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 public function findAllByFilterPaged(int $userId, int $page = 1, int $limit = 10): Pagination
{ {
$queryBuilder = $this->getFilterQuery($userId); $queryBuilder = $this->getFilterQuery($userId);
...@@ -53,37 +61,63 @@ class QuestRepository extends ServiceEntityRepository ...@@ -53,37 +61,63 @@ class QuestRepository extends ServiceEntityRepository
if ($page > $maxPage) { if ($page > $maxPage) {
$page = (int)$maxPage; $page = (int)$maxPage;
} }
$result->page = $page; if ($page > 0) {
$result->maxPage = $maxPage; $result->page = $page;
$result->limit = $limit; $result->maxPage = $maxPage;
$result->limit = $limit;
$paginator->getQuery()
->setFirstResult(($page - 1) * $limit) $paginator->getQuery()
->setMaxResults($limit); ->setFirstResult(($page - 1) * $limit)
->setMaxResults($limit);
}
$result->quests = $paginator->getQuery()->getResult(); $result->quests = $paginator->getQuery()->getResult();
return $result; return $result;
} }
/**
* Получение пройденных квестов
*
* @param int $userId
*
* @return array
*
* @throws QueryException
*/
public function findCompletedByFilter(int $userId): array public function findCompletedByFilter(int $userId): array
{ {
$queryBuilder = $this->getFilterQuery($userId); $queryBuilder = $this->getBaseQuery();
$criteria = Criteria::create();
$expr = Criteria::expr();
if (!$expr) {
return [];
}
$currentDate = new \DateTime(); $currentDate = new \DateTime();
$queryBuilder->setParameter('current', $currentDate) $criteria
->andWhere('q.date < :current'); ->andWhere($expr->lt('date', $currentDate))
->andWhere($expr->eq('appointments.related_user', $userId));
$queryBuilder->setParameter('user_id', $userId) $queryBuilder->addCriteria($criteria);
->leftJoin('q.appointments', 'appointments')
->andWhere('appointments.related_user = :user_id');
return $queryBuilder->getQuery()->getResult(); 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 public function findOneById(int $id, int $userId, bool $cache = true): ?Quest
{ {
$queryBuilder = $this->getBaseQuery($userId); $queryBuilder = $this->getBaseQuery();
$queryBuilder->setParameter('detail_id', $id) $queryBuilder->setParameter('detail_id', $id)
->andWhere('q.id = :detail_id'); ->andWhere('q.id = :detail_id');
$query = $queryBuilder->getQuery(); $query = $queryBuilder->getQuery();
...@@ -93,87 +127,48 @@ class QuestRepository extends ServiceEntityRepository ...@@ -93,87 +127,48 @@ class QuestRepository extends ServiceEntityRepository
return $query->getOneOrNullResult(); return $query->getOneOrNullResult();
} }
private function getBaseQuery(int $userId): QueryBuilder /**
* Получение квестов по критерии
*
* @param Criteria $criteria
*
* @return array
*/
public function getByCriteria(Criteria $criteria): array
{ {
return $this->createQueryBuilder('q'); return $this->getQueryByCriteria($criteria)->getQuery()->getResult();
} }
private function getFilterQuery(int $userId): QueryBuilder private function getBaseQuery(): QueryBuilder
{ {
$queryBuilder = $this->getBaseQuery($userId); return $this->createQueryBuilder('q')
->leftJoin('q.genre', 'genre')
$redisFilter = new RedisFilter($userId); ->leftJoin('q.theme', 'theme')
$filter = $redisFilter->get(); ->leftJoin('q.tags', 'tags')
if ($filter instanceof FilterDto) { ->leftJoin('q.appointments', 'appointments')
if (!empty($filter->search)) { ->leftJoin('q.reviews', 'reviews');
$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 private function getQueryByCriteria(Criteria $criteria): QueryBuilder
{ {
$queryBuilder = $this->createQueryBuilder('q'); $queryBuilder = $this->getBaseQuery();
$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) $queryBuilder->addCriteria($criteria);
->setParameter('end', $endDate)
->andWhere('q.date >= :start')
->andWhere('q.date <= :end');
return $queryBuilder->getQuery()->getResult(); return $queryBuilder;
} }
public function getEndQuests(): array private function getFilterQuery(int $userId): QueryBuilder
{ {
$queryBuilder = $this->createQueryBuilder('q'); $redisFilter = new RedisFilter($userId);
$filter = $redisFilter->get();
$startDate = new \DateTime(); if ($filter instanceof FilterDto) {
$startDate->setTime(0,0); $criteria = $filter->getCriteria();
$startDate->sub(new DateInterval('P1D')); $queryBuilder = $this->getQueryByCriteria($criteria);
$endDate = new \DateTime(); } else {
$endDate->setTime(23,59, 59); $queryBuilder = $this->getBaseQuery();
$endDate->sub(new DateInterval('P1D')); }
return $queryBuilder;
$queryBuilder->setParameter('start', $startDate)
->setParameter('end', $endDate)
->andWhere('q.date >= :start')
->andWhere('q.date <= :end');
return $queryBuilder->getQuery()->getResult();
} }
// /** // /**
......
...@@ -3,12 +3,23 @@ ...@@ -3,12 +3,23 @@
namespace App\Service\Dto\Classes; namespace App\Service\Dto\Classes;
use App\Service\Dto\BaseDto; use App\Service\Dto\BaseDto;
use Doctrine\Common\Collections\Criteria;
use Symfony\Component\DependencyInjection\Attribute\AsAlias; use Symfony\Component\DependencyInjection\Attribute\AsAlias;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
#[AsAlias(id: 'dto.filter', public: true)] #[AsAlias(id: 'dto.filter', public: true)]
class FilterDto extends BaseDto class FilterDto extends BaseDto
{ {
public const SORT_TYPES = [
'По возрастанию' => 'ASC',
'По убыванию' => 'DESC'
];
public const SORT_FIELDS = [
'Название' => 'name',
'Дата проведения' => 'date',
'Дата финальной записи' => 'final_date'
];
/** /**
* @var string|null * @var string|null
*/ */
...@@ -44,4 +55,44 @@ class FilterDto extends BaseDto ...@@ -44,4 +55,44 @@ class FilterDto extends BaseDto
*/ */
#[Groups(['data'])] #[Groups(['data'])]
public array $themes; public array $themes;
/**
* Получение фильтра ORM
*
* @return Criteria
*/
public function getCriteria(): Criteria
{
$criteria = Criteria::create();
$expr = Criteria::expr();
if (!$expr) {
return $criteria;
}
if (!empty($this->search)) {
$text = $this->search;
$criteria->orWhere($expr->contains('name', $text))
->orWhere($expr->contains('short_description', $text))
->orWhere($expr->contains('full_description', $text));
}
if ($genres = $this->genres) {
$criteria->andWhere($expr->in('genre.name', $genres));
}
if ($themes = $this->themes) {
$criteria->andWhere($expr->in('theme.name', $themes));
}
if ($tags = $this->tags) {
$criteria->andWhere($expr->in('tags.name', $tags));
}
if ($this->sort
&& $this->sortField
&& in_array($this->sort, self::SORT_TYPES, true)
&& in_array($this->sortField, self::SORT_FIELDS, true)
) {
$criteria->orderBy([$this->sortField => $this->sort]);
}
return $criteria;
}
} }
\ No newline at end of file
...@@ -5,7 +5,7 @@ namespace App\Service\Response\Classes\Data; ...@@ -5,7 +5,7 @@ namespace App\Service\Response\Classes\Data;
use App\Entity\Genre; use App\Entity\Genre;
use App\Entity\Tag; use App\Entity\Tag;
use App\Entity\Theme; use App\Entity\Theme;
use App\Repository\QuestRepository; use App\Service\Dto\Classes\FilterDto;
use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\Groups;
class Filter class Filter
...@@ -32,11 +32,11 @@ class Filter ...@@ -32,11 +32,11 @@ class Filter
* @var string[] * @var string[]
*/ */
#[Groups(['filter'])] #[Groups(['filter'])]
public array $sortFields = QuestRepository::SORT_FIELDS; public array $sortFields = FilterDto::SORT_FIELDS;
/** /**
* @var string[] * @var string[]
*/ */
#[Groups(['filter'])] #[Groups(['filter'])]
public array $sorts = QuestRepository::SORT_TYPES; public array $sorts = FilterDto::SORT_TYPES;
} }
\ No newline at end of file