<?php
namespace App\Service\Entry;
use App\Form\FreeWordType;
use App\Repository\Entry\EntryRepository;
use App\Utils\PaginationUtil;
use App\Utils\QbShortcutTrait;
use App\Utils\TargetChoiceUtil;
use Doctrine\ORM\QueryBuilder;
use Psr\Container\ContainerInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class FreeWordSearchService
{
use QbShortcutTrait;
private const MAX_RESULTS = 4;
private ContainerInterface $container;
private UrlGeneratorInterface $urlGenerator;
private EntryRepository $entryRepository;
public function __construct(
ContainerInterface $container,
UrlGeneratorInterface $urlGenerator,
EntryRepository $entryRepository
) {
$this->container = $container;
$this->urlGenerator = $urlGenerator;
$this->entryRepository = $entryRepository;
}
public function getForm(): FormInterface
{
return $this->container->get('form.factory')->create(FreeWordType::class, null, [
"action" => $this->urlGenerator->generate('search_index'),
"method" => "GET",
"csrf_protection" => false
]);
}
public function getQueryBuilder(int $category, string $alias = "a"): QueryBuilder
{
$qb = $this->entryRepository->getListQuery([]);
$qb
->andWhere($qb->expr()->eq('e.category', ':category'))
->setParameter('category', $category)
;
$this->entryRepository->setDefaultOrder($qb);
$this->entryRepository->addPublishWhere($qb);
return $qb;
}
public function addWordSearch(QueryBuilder $qb, FormInterface $form): self
{
$this->qbsWord(
$qb,
[
"word" => $form->get('word')->getData()
],
"word",
[
"e.title",
"e.title_en",
"e.title_cn",
"e.title_tw",
"e.summaryTitle",
"e.summaryTitle_en",
"e.summaryTitle_cn",
"e.summaryTitle_tw",
"e.summaryContent",
"e.summaryContent_en",
"e.summaryContent_cn",
"e.summaryContent_tw",
]
);
return $this;
}
public function search(Request $request, int $currentPage = 1): array
{
$form = $this->getForm();
$form->handleRequest($request);
return [
"form" => $form,
"modelPlan" => $this->getResult($form, TargetChoiceUtil::MODELPLAN, $currentPage),
"workSpace" => $this->getResult($form, TargetChoiceUtil::WORKSPACE, $currentPage),
"hotel" => $this->getResult($form, TargetChoiceUtil::HOTEL, $currentPage),
"activity" => $this->getResult($form, TargetChoiceUtil::ACTIVITY, $currentPage),
"mobility" => $this->getResult($form, TargetChoiceUtil::MOBILITY, $currentPage)
];
}
public function getSingleResult(Request $request, int $category): array
{
$form = $this->getForm();
$form->handleRequest($request);
$page = $request->query->has('page')? $request->query->get('page'): 1;
return $this->getResult($form, $category, $page);
}
public function getResult(FormInterface $form, int $category, int $currentPage): array
{
$qb = $this->getQueryBuilder($category);
$this->addWordSearch($qb, $form);
if($category === TargetChoiceUtil::MODELPLAN) {
$qb->orderBy("RAND()");
} else {
$qb->orderBy("e.id", "desc");
}
$pagination = new PaginationUtil($qb, $currentPage, self::MAX_RESULTS);
return [
"iterator" => $pagination->getPaginator()->getIterator(),
"nextPage" => $pagination->getNextPage(),
"isLast" => $pagination->isLastPage(),
"itemCount" => $pagination->getPaginator()->count(),
"category" => $category
];
}
}