<?php
namespace WebBundle\Controller;
use Exception;
use FlexApp\DTO\RequestCatalogDTO;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use WebBundle\Helper\App;
use WebBundle\Helper\FilterHelper;
use WebBundle\Helper\HideFactoryCountriesHelper;
use WebBundle\Helper\RequestHelper;
use WebBundle\Helper\SearchLogHelper;
use WebBundle\Helper\StatsHelper;
use WebBundle\Repository\CollectionRepository;
use WebBundle\Repository\FactoryRepository;
use WebBundle\Repository\FilterRepository;
use WebBundle\Repository\PublicationRepository;
use WebBundle\Service\ReviewsService;
use WebBundle\Service\SearchService;
use WebBundle\Service\SphinxSearcherService;
use WebBundle\Service\VisitedService;
class CatalogController extends ExtendedController
{
/** @required */
public PublicationRepository $publicationRepository;
/** @required */
public FilterRepository $filterRepository;
/** @required */
public CollectionRepository $collectionRepository;
/** @required */
public FactoryRepository $factoryRepository;
/** @required */
public VisitedService $visitedService;
/** @required */
public SphinxSearcherService $sphinxSearcherService;
/** @required */
public ReviewsService $reviewsService;
/** @required */
public SearchService $searchService;
public function indexAction(Request $request, ?string $key = null, $subkey = null): Response
{
ini_set('memory_limit', '2048M');
$reqCatDTO = new RequestCatalogDTO($request, $key, $subkey);
$oSSearch = $this->searchService->setFilter($reqCatDTO);
// перенаправляем на верную страницу каталога
if ($oSSearch->isRedirect()) {
return $oSSearch->getRedirect();
}
if ($oSSearch->filterService()->isTestingBrand()) {
if (!App::isRole('ROLE_TEST')) {
throw new NotFoundHttpException('factory not found');
}
}
$dataFilterSearch = $oSSearch->getSearchKey() ? $oSSearch->getReplaceParentWithChildren() : [];
$subkey = $oSSearch->getSearchSubKey();
// $oSSearch->setGCount(true); //Тогда будет считать
$result = $oSSearch->getResult();
$calculate = $oSSearch->getCalculate();
$limit = $oSSearch->getLimit();
$pageCount = intval(ceil($result['count'] / ($limit ?: 1)));
$linkSamples = null;
if ($oSSearch->isPageExpressSample()) {
$linkSamples = $this->publicationRepository->getUrlBlogExpressSamples();
}
$factory = null;
if ($oSSearch->filterService() && $oSSearch->filterService()->getCurBrand()) {
$factoryId = $oSSearch->filterService()->getCurBrand()->getId();
$factory = $this->factoryRepository->find($factoryId);
}
$factoryReviewsUrl = $factory ? $this->generateUrl('factory_reviews', ['id' => $factory->getId()]) : "";
$avgReviewsStar = 0;
if ($factory) {
$reviews = $this->reviewsService->getReviewsByFactory($factory);
$sum = 0;
$count = 0;
foreach ($reviews as $collection) {
foreach ($collection['reviews'] as $review) {
$sum += $review['star'];
$count++;
}
}
if ($count > 0) {
$avgReviewsStar = round($sum / $count, 2);
}
}
$output = [
'content' => [
'h1' => $oSSearch->getTitleHtml(),
'html' => $oSSearch->getHtml(),
'amount' => $oSSearch->getAmount(),
'key' => $key,
'subkey' => $subkey,
'fullKey' => $key . $subkey ? "/$subkey" : '',
'brand' => $oSSearch->filterService()->getCurBrand(),
'isDesigner' => $oSSearch->isDesignerStyle(),
],
'meta' => [
'title' => $oSSearch->getMetaManager()->getTitle(),
'description' => $oSSearch->getMetaManager()->getDescription(),
'keywords' => $oSSearch->getMetaManager()->getKeywords(),
],
'result' => $result,
'activeFilters' => $oSSearch->getFiltersGTM(),
'page' => $oSSearch->getPage(),
'pageCount' => $pageCount,
'limit' => $limit,
'sortId' => $oSSearch->getSearchSortId(),
'sortList' => $oSSearch->getSortList(),
'discount' => $oSSearch->getDiscount(),
'top20' => $oSSearch->getTop20(),
'dataFilterSearch' => json_encode($dataFilterSearch),
'gclid' => $request->query->get('gclid', null),
'noindex' => $oSSearch->isNoindex(),
'isPageReleaseYear' => $oSSearch->isPageReleaseYear(),
'isPageExhibition' => $oSSearch->isPageExhibition(),
'linkSamples' => $linkSamples,
'factoryReviewsUrl' => $factoryReviewsUrl,
];
$output['calculate'] = $calculate ?? []; //попытка передать в твиг
if ($oSSearch->filterService() && $oSSearch->filterService()->getCurBrand()) {
$factoryId = $oSSearch->filterService()->getCurBrand()->getId();
$factory = $this->factoryRepository->find($factoryId);
$collections = $this->reviewsService->getReviewsByFactory($factory);
$reviewsTotalCount = 0;
foreach ($collections as $c) {
$reviewsTotalCount += count($c['reviews']);
}
$output['result']['reviewsTotalCount'] = $reviewsTotalCount;
$output['result']['avgReviewsStar'] = $avgReviewsStar;
// $output['result']['factoryReviews'] = $factory ? $this->reviewsService->getReviewsByFactory($factory) : null;
}
StatsHelper::addHits($oSSearch->filterService());
SearchLogHelper::save(['url' => App::getRequest()->getUri(), 'title' => $oSSearch->getMetaManager()->getTitle()]);
$output['noFloor'] = true;
$keyUrl = FilterHelper::checkPageUrl('recently-added-tiles');
$topWeek = FilterHelper::checkPageUrl('top-week');
$topMonth = FilterHelper::checkPageUrl('top-month');
// if ($key == $topWeek || $key == $topMonth || ($key != null && $keyUrl == $key)) {
// unset($output['result']['fReview']);
// }
unset($output['result']['fReview']);
// http://te.loc/ru/catalogue/novogres?debug=1
// переадресация на каталог с сообщением если сняли фабрику
// https://te.remote.team/#/discus/98061423-1D64-57EB-547F-90E7AD5E8305/
// убрали переaдресацию, теперь просто показываем сообщение и скрываем результаты показа
if (
$oSSearch->isBrands()
&& $oSSearch->isOneFilter()
&& (
$oSSearch->filterService()->getCurBrand()->getStatus() == 2
|| in_array($oSSearch->filterService()->getCurBrand()->getId(), HideFactoryCountriesHelper::codes())
)
) {
$output['fMsg'] = [
'name' => $oSSearch->filterService()->getCurBrand()->getName(),
'url' => $this->generateUrl('app_catalog'),
];
} else {
// принято решение страницу дизайнера, который не имеет активных коллекций переадресовывать на список дизайнеров
if ($oSSearch->isOneFilter() && $oSSearch->isDesigner() && $oSSearch->getResult()['count'] == 0) {
$keyUrl = FilterHelper::checkPageUrl('designer');
$msg = trim(str_replace('edit', '', html_entity_decode(strip_tags($oSSearch->getTitleHtml()))));
$output['msg'] = [
'name' => $msg,
'url' => $this->generateUrl('app_catalog', ['key' => $keyUrl]),
];
}
}
$this->visitedService->addHistory($oSSearch);
if (RequestHelper::isAjax()) {
if ($oSSearch->getPage() == 1 and !$reqCatDTO->isOnlyPage()) {
$response = new JsonResponse(
[
'content' => $this->render('@Web/Catalog/search-content.html.twig', $output)->getContent(),
'key' => $oSSearch->getSearchKey(),
'url' => urldecode($this->generateUrl(
'app_catalog',
['key' => $oSSearch->getSearchKey(), 'subkey' => $subkey]
)),
'dataFilterSearch' => $dataFilterSearch,
'title' => $oSSearch->getMetaManager()->getTitle(),
'isDesigner' => $oSSearch->isDesignerStyle(),
'isPageReleaseYear' => $oSSearch->isPageReleaseYear(),
'isPageExhibition' => $oSSearch->isPageExhibition(),
'page' => $oSSearch->getPage(),
'pageCount' => $pageCount,
'limit' => $limit,
'count' => $result['count'],
'calculate' => $calculate,
'history' => [
'all' => $this->visitedService->getCountHistory(),
'list' => $this->render('@Web/Visit/last.html.twig', ['visited' => $this->visitedService->getLastHistory()])->getContent(),
],
'factoryReviewsUrl' => $factoryReviewsUrl,
'avgReviewsStar' => $avgReviewsStar,
]
);
$key = $key ?: $oSSearch->getSearchKey();
if (!$oSSearch->getSearchKey()) {
$oSSearch->setSearchKey($key);
}
} else {
$response = new JsonResponse(
[
'content' => $this->render('@Web/Catalog/search-result.html.twig', $output)->getContent(),
'page' => $oSSearch->getPage(),
'pageCount' => $pageCount,
'limit' => $limit,
'count' => $result['count'],
]
);
}
} else {
$response = $this->render('@Web/Catalog/index.html.twig', $output); // 179 ms
}
// чистим временную сортировку каталога
App::getSession()->remove('sort_catalog_tmp');
return $response;
}
/**
* @param string $key
* @param $filterKey
* @return Response
* @throws Exception
*/
public function filtersAction(string $key, $filterKey)
{
$_locale = App::getRequest()->get('_locale');
$_locale = $_locale ?: App::getCurLocale();
//////////////////////////////////////
// заплатка для локагей вида en_us
// разбираем локаль и формируем на основании первой части
// на выдачу меняем локаль сформированную на исходную
$a_locale = explode('-', $_locale);
$_locale_replace = null;
if (count($a_locale) > 1) {
$_locale_replace = $_locale;
$_locale = $a_locale[0];
}
//////////////////////////////////////
// запрос фильтрации НЕ из каталога через лефт меню
if ($key == 'add') {
$word = FilterHelper::getWord(null, $_locale);
$url = FilterHelper::getUrl(null, $_locale, $_locale_replace);
return $this->ok([
'post' => RequestHelper::get(),
'url' => $url,
'word' => $word,
]);
} elseif ($key == 'get-uri') {
$word = FilterHelper::getWord($filterKey, $_locale);
$url = FilterHelper::getUrl($filterKey, $_locale, $_locale_replace);
return $this->ok([
'url' => $url,
'word' => $word,
'$key' => $key,
'_locale' => $_locale,
'$filterKey' => $filterKey,
]);
} elseif ($key == 'list-designer') {
$isReact = $filterKey == 'react';
$aids = [];
// адский костыль, но пока иначе никак
// получаем выдачу коллекций и по ним формируем список дизайнеров
$referer = !empty($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
if ($referer) {
$keyNorm = explode('/', $referer);
$keyNorm = array_pop($keyNorm);
$keyNorm = explode('?', $keyNorm);
$keyNorm = $keyNorm[0];
$keyNorm = explode('&', $keyNorm);
$searchFilter = $this->filterRepository->getFiltersForSearchSphinx($keyNorm, $_locale);
$data = [
"searchFilter" => $searchFilter,
"searchSort" => "3",
"searchPeriod" => null,
"locale" => $_locale,
];
$sphRes = $this->sphinxSearcherService->searchSphinx($data, 3, false, true, true);
$allCalculate = $sphRes['res']['calculate'] ?? $sphRes['calculate'];
$sphRes = $sphRes['res']['collections'] ?? $sphRes['collections'];
$cids = array_column($sphRes, 'c_id');
if ($cids) {
$aids = $this->collectionRepository->getCollAuthorIds($cids);
}
}
// получение и формирования списка дизайнеров в каталоге /.../catalogue/designer
$listDesigner = $this->filterRepository->getListDesignersForCataloge($aids);
$listDesignersCnt = count($listDesigner);
$aLlistDesigner = [];
$keyDesignerStyle = $this->filterRepository->getKeyDesignerStyle($_locale);
$keysNew = !empty($keyNorm) ? array_diff($keyNorm, [$keyDesignerStyle]) : [];
foreach ($listDesigner as $des) {
$firstLetter = $des['name'][0];
$des['slug'] .= !empty($keysNew) ? '&' . implode('&', $keysNew) : '';
$des['url'] = urldecode($this->generateUrl('app_catalog', ['key' => $des['slug']]));
$des['active'] = $filterKey == $des['oldId'];
$des['cnt'] = $allCalculate['getDesigner'][$des['id']] ?? 0;
if ($des['cnt']) {
$aLlistDesigner[$firstLetter][] = $des;
}
}
if ($isReact) {
$content = $aLlistDesigner;
} else {
$output = $this->render('@Web/Catalog/menu_designers.html.twig', ['listDesigners' => $aLlistDesigner]);
$content = $output->getContent();
}
return $this->ok([
'allCount' => $listDesignersCnt,
'content' => $content,
]);
} else {
return $this->error("fail filtersAction not $key");
}
}
}