<?php
namespace Slivki\Controller;
use Slivki\Entity\Banner;
use Slivki\Entity\Category;
use Slivki\Entity\City;
use Slivki\Entity\Comment;
use Slivki\Entity\EntityVote;
use Slivki\Entity\MainMenu;
use Slivki\Entity\Sale;
use Slivki\Entity\SaleLoadMoreBtnDescription;
use Slivki\Entity\SaleProduct;
use Slivki\Entity\UserGroup;
use Slivki\Entity\Visit;
use Slivki\Entity\VisitCounter;
use Slivki\Enum\SwitcherFeatures;
use Slivki\Repository\OfferRepository;
use Slivki\Repository\SaleRepository;
use Slivki\Services\Category\CategoryCacheService;
use Slivki\Services\Offer\OfferCacheService;
use Slivki\Services\Sale\CategoryBoxService;
use Slivki\Services\Sale\SaleCacheService;
use Slivki\Services\Switcher\ServerFeatureStateChecker;
use Slivki\Util\CommonUtil;
use Slivki\Util\SoftCache;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class SaleController extends SiteController
{
/**
* @Route("/skidki-i-rasprodazhi", name="sales")
*/
public function indexAction(
Request $request,
CategoryBoxService $categoryBoxService,
OfferCacheService $offerCacheService,
SaleCacheService $saleCacheService,
ServerFeatureStateChecker $serverFeatureStateChecker
) {
if (!$serverFeatureStateChecker->isServerFeatureEnabled(SwitcherFeatures::SALES())) {
return new Response('', Response::HTTP_NOT_FOUND);
}
$isMobileDevice = self::getMobileDevice($request);
$data = [];
$saleMenu = $this->getCategoryRepository()->getSaleCategoriesSortedBySaleVisits();
$companyNewsSaleCategory = null;
$data['saleMenu'] = [];
foreach ($saleMenu as $menuItem) {
$data['saleMenu'][] = ['category' => $menuItem];
}
$data['categoryList'] = $this->getSaleCategoryList($categoryBoxService, 0, 2, false, $isMobileDevice);
$data['offerRateSchedule'] = $this->getOfferRateSchedule($request->getSession());
$data['firstBanner'] = $this->getBannerRepository()->findOneBy(['typeID' => Banner::TYPE_SALE_BANNER, 'active' => true, 'positionRow' => 1]);
$data['secondBanner'] = $this->getBannerRepository()->findOneBy(['typeID' => Banner::TYPE_SALE_BANNER, 'active' => true, 'positionRow' => 2]);
$data['menuSelected'] = MainMenu::MENU_ID_SALE;
$softCache = new SoftCache(SaleRepository::CACHE_NAME);
$data['saleVisitCount'] = $softCache->get(SaleRepository::VISIT_COUNT_CACHE_KEY);
$data['visitedSales'] = $softCache->get(SaleRepository::VISITED_SALE_COUNT_CACHE_KEY);
$data['saleVisitCountTooltip'] = 'Количество читателей раздела "Новости скидок" за 30 дней';
$data['visitedSalesTooltip'] = 'Количество прочитанных статей за 30 дней';
$data['currentCategoryID'] = 0;
$mainHotFeed = '';
foreach ($this->getMainHotFeed($offerCacheService, $saleCacheService, 20) as $entity) {
$mainHotFeed .= $this->renderView($isMobileDevice ? 'Slivki/mobile/hot_feed_teaser.html.twig' : 'Slivki/top_main_feed_teaser_mobile.html.twig', $entity);
}
$data['mainHotFeed'] = $mainHotFeed;
$data['locationInfo'] = '';
$deviceType = $isMobileDevice ? self::DEVICE_TYPE_MOBILE : self::DEVICE_TYPE_DESKTOP;
$this->addVisit(0, Visit::TYPE_SALE_MAIN_PAGE, $deviceType, $this->getUser(), $request->getClientIp(), $request->headers->get('referer', ''));
return $this->render($isMobileDevice ? 'Slivki/mobile/sale/index.html.twig' : 'Slivki/sale/index.html.twig', $data);
}
/**
* @Route("/skidki-i-rasprodazhi/get-category-box")
*/
public function getSaleCategoryBoxListAction(Request $request, CategoryBoxService $categoryBoxService) {
$offset = $request->request->get('offset', 0);
$length = $request->request->get('length', 1);
$data['categoryList'] = $this->getSaleCategoryList($categoryBoxService, $offset, $length, true, self::getMobileDevice($request));
if (empty($data['categoryList'])) {
$response = new Response('');
} else {
$response = $this->render(self::getMobileDevice($request) ? 'Slivki/mobile/sale/category.html.twig'
: 'Slivki/sale/sale_list_box.html.twig', $data);
}
return $response;
}
private function getSaleCategoryList(CategoryBoxService $categoryBoxService, $offset, $length, $excludeNewCategory = false, $isMobileDevice = false) {
$categoryList = $this->getCategoryRepository()->getSaleCategoriesSortedBySaleVisits();
$result = [];
$categoryList = array_slice($categoryList, $offset, $length);
if ($length == 1 && $excludeNewCategory && isset($categoryList[0]) && $categoryList[0]->getID() == Category::NEW_SALE_CATEGORY_ID) {
return $this->getSaleCategoryList($offset + 1, 1);
}
foreach ($categoryList as $category) {
$result[] = [
"category" => $category,
"categoryBox" => $categoryBoxService->getCategoryBox($category->getID(), false, $isMobileDevice)
];
}
return $result;
}
//TODO: total refactoring this piece of shit and related functions
public function categoryAction(
Request $request,
CategoryBoxService $categoryBoxService,
CategoryCacheService $categoryCacheService,
ServerFeatureStateChecker $serverFeatureStateChecker,
$entityID
) {
if (!$serverFeatureStateChecker->isServerFeatureEnabled(SwitcherFeatures::SALES())) {
return new Response('', Response::HTTP_NOT_FOUND);
}
$isMobileDevice = self::getMobileDevice($request);
$categoryRepository = $this->getCategoryRepository();
$category = $categoryRepository->findCached($entityID);
if (!$category) {
return $this->redirect("/");
}
$isChildOfFlier = $category['category']->isChildOf(Category::FLIER_SALE_CATEGORY_ID);
if ($entityID == Category::FLIER_SALE_CATEGORY_ID || $isChildOfFlier) {
return $this->fliersAction($request, $category);
}
$isChildOfVideoguide = $category['category']->isChildOf(Category::SALE_VIDEO_GUIDE_CATEGORY_ID) ||
$category['category']->isChildOf(Category::SALE_VIDEO_GUIDE_AUTORS_CATEGORY_ID);
if ($entityID == Category::SALE_VIDEO_GUIDE_CATEGORY_ID || $isChildOfVideoguide) {
return $this->videoguidesAction($request, $categoryBoxService, $category);
}
$categoryRepository = $this->getCategoryRepository();
$topParentCategory = $category['category']->getTopParentCategory();
$parentId = $topParentCategory instanceof Category && $topParentCategory->getID() !== $entityID ? $topParentCategory->getID() : 0;
$categoryList = $categoryRepository->getActiveCategories($parentId, [Category::DEFAULT_CATEGORY_TYPE], Category::SALE_CATEGORY_ID);
$categoryListHasCategory = false;
foreach ($categoryList as $item) {
if ((int) $item->getID() === $entityID) {
$categoryListHasCategory = true;
break;
}
}
if (!$categoryListHasCategory) {
$categoryList[] = $category['category'];
}
if ($parentId > 0) {
$data['parentCategory'] = $this->getCategoryRepository()->findCached($parentId);
}
foreach ($categoryList as $key => $value) {
$categoryList[$key] = [
'category' => $value,
'categoryBox' => $value->getID() == $entityID ? $categoryBoxService->getCategoryBox($entityID, true, $isMobileDevice) : false
];
}
$data['categoryList'] = $categoryList;
$data['offerRateSchedule'] = $this->getOfferRateSchedule($request->getSession());
$data['searchIn'] = SearchController::SEARCH_SALES;
if ($this->getUser() && in_array($this->getUser()->getEmail(), ['anna@slivkki.by', 'maxmailmax@gmail.com', 'igor@slivki.by'])) {
$categoryMonthlyVisitCache = new SoftCache(Visit::CATEGORY_MONTHLY_VISITS_CACHE_NAME);
$currentCategoryMonthlyVisits = $categoryMonthlyVisitCache->get($entityID);
if ($currentCategoryMonthlyVisits) {
$data['currentCategoryMonthlyVisits'] = $currentCategoryMonthlyVisits;
}
}
$data['currentCategory'] = $category;
$data['currentCategoryID'] = $entityID;
$data['unfoldedCategory'] = true;
$data['menuSelected'] = MainMenu::MENU_ID_SALE;
if ($entityID == Category::PHOTOGUIDE_SALE_CATEGORY_ID) {
$data['searchIn'] = SearchController::SEARCH_PHOTO_GUIDES;
$data['menuSelected'] = MainMenu::MENU_ID_PHOTOGUIDE;
}
$softCache = new SoftCache(SaleRepository::CACHE_NAME);
$data['saleVisitCount'] = $softCache->get(SaleRepository::VISIT_COUNT_CACHE_KEY);
$data['visitedSales'] = $softCache->get(SaleRepository::VISITED_SALE_COUNT_CACHE_KEY);
$data['saleVisitCountTooltip'] = 'Количество читателей раздела "Новости скидок" за 30 дней';
$data['visitedSalesTooltip'] = 'Количество прочитанных статей за 30 дней';
$data['saleMenu'] = $categoryList;
$deviceType = $isMobileDevice ? self::DEVICE_TYPE_MOBILE : self::DEVICE_TYPE_DESKTOP;
$this->addVisit($entityID, Visit::TYPE_SALE_CATEGORY, $deviceType, $this->getUser(), $request->getClientIp(),
$request->headers->get('referer', ''));
return $this->render($isMobileDevice ? 'Slivki/mobile/sale/index.html.twig' : 'Slivki/sale/index.html.twig', $data);
}
public function videoguidesAction(Request $request, CategoryBoxService $categoryBoxService, $category) {
$isMobileDevice = self::getMobileDevice($request);
$categoryID = $category['category']->getID();
$categoryRepository = $this->getCategoryRepository();
$data['isVideoguideCategory'] = true;
$data['videoguideCategoryMenu'] = $categoryRepository->getSaleVideoguideCategoryMenu();
$data['videoguideAutorsCategoryMenu'] = '';
$data['menuSelected'] = Category::SALE_VIDEO_GUIDE_CATEGORY_ID;
$softCache = new SoftCache(SaleRepository::CACHE_NAME);
$data['saleVisitCountTooltip'] = 'Количество читателей раздела "Новости скидок" за 30 дней';
$data['visitedSalesTooltip'] = 'Количество прочитанных статей за 30 дней';
$data['saleVisitCount'] = $softCache->get(SaleRepository::VISIT_COUNT_CACHE_KEY);
$data['visitedSales'] = $softCache->get(SaleRepository::VISITED_SALE_COUNT_CACHE_KEY);
$data['currentCategory'] = $category;
$data['currentCategoryID'] = $categoryID;
$data['unfoldedCategory'] = true;
$user = $this->getUser();
$data['statViewer'] = $user and $this->isGranted('ROLE_MANAGER_STATISTICS');
$deviceType = $isMobileDevice ? self::DEVICE_TYPE_MOBILE : self::DEVICE_TYPE_DESKTOP;
if ($categoryID == Category::SALE_VIDEO_GUIDE_CATEGORY_ID) {
$this->addVisit(0, Visit::TYPE_SLIVKI_TV_MAIN_PAGE, $deviceType, $this->getUser(), $request->getClientIp());
} else {
$this->addVisit($categoryID, Visit::TYPE_SLIVKI_TV_CATEGORY, $deviceType, $this->getUser(), $request->getClientIp());
}
$view = $isMobileDevice ? 'Slivki/mobile/sale/index.html.twig' : 'Slivki/sale/index.html.twig';
if ($categoryID == Category::SALE_VIDEO_GUIDE_CATEGORY_ID) {
$data['categoryHTML'] = $categoryBoxService->getVideoGuidesMainPage($isMobileDevice);
$view = $isMobileDevice ? 'Slivki/mobile/sale/videoguide/index.html.twig' : 'Slivki/sale/videoguide_index.html.twig';
} else {
$videoguideCategoryList[0]['category'] = $category['category'];
$videoguideCategoryList[0]['categoryBox'] = $categoryBoxService->getCategoryBox($categoryID, true, $isMobileDevice);
$data['isChildOfVideoGuide'] = true;
$data['categoryList'] = $videoguideCategoryList;
$data['videoguideCategory'] = $categoryRepository->findCached(Category::SALE_VIDEO_GUIDE_CATEGORY_ID);
}
return $this->render($view, $data);
}
public function fliersAction(Request $request, $category) {
$isChildOfFlier = $category['category']->isChildOf(Category::FLIER_SALE_CATEGORY_ID);
$softCache = new SoftCache(SaleRepository::CACHE_NAME);
$data['menuSelected'] = MainMenu::MENU_ID_FLIER;
$data['searchIn'] = SearchController::SEARCH_FLIERS;
$data['saleVisitCount'] = $softCache->get(SaleRepository::FLIER_VISIT_COUNT_CACHE_KEY);
$data['visitedSales'] = $softCache->get(SaleRepository::VISITED_FLIER_COUNT_CACHE_KEY);
$data['saleVisitCountTooltip'] = 'Количество читателей раздела "Листовки" за 30 дней';
$data['visitedSalesTooltip'] = 'Количество прочитанных листовок за 30 дней';
$data['currentCategoryID'] = $category['category']->getID();
$data['currentCategory'] = $category;
$mainMenuRepository = $this->getDoctrine()->getManager()->getRepository(MainMenu::class);
$flierMenu = $mainMenuRepository->getItemListCached(MainMenu::MENU_ID_FLIER, City::DEFAULT_CITY_ID);
$flierMenuCount = 0;
$cityName = $request->query->get('city');
$selectedCity = null;
if ($cityName) {
$cityList = $softCache->get(SaleRepository::CITIES_CACHE_KEY);
foreach ($cityList as $item) {
$firstChar = mb_substr($cityName, 0, 1);
if (isset($cityList[$firstChar])) {
foreach ($cityList[$firstChar] as $city) {
if ($city['cityName'] == $cityName) {
$selectedCity = $city;
$data['selectedCity'] = $cityName;
break;
}
}
}
}
}
$flierMenuTemp = [];
foreach ($flierMenu as $flierMenuItem) {
if (in_array($flierMenuItem->getType(), [MainMenu::TYPE_OFFER_CATEGORY, MainMenu::TYPE_SALE_CATEGORY])) {
$flierCategory = $this->getCategoryRepository()->findCached($flierMenuItem->getEntityID());
if ($flierCategory) {
$entityCount = 0;
if ($selectedCity) {
$entityCount = count(array_unique(array_intersect($selectedCity['entityList'], $flierCategory['entityList'])));
} else {
$entityCount = $flierCategory['category']->getEntityCount();
}
if ($entityCount > 0) {
$flierMenuItem->setEntityCount($entityCount);
$flierMenuCount += $entityCount;
$flierMenuTemp[] = $flierMenuItem;
}
}
}
}
$flierMenu = $flierMenuTemp;
$cityList = $softCache->get(SaleRepository::CITIES_CACHE_KEY);
$data['cityList'] = $cityList ? $cityList : [];
$flierCategoryList = [];
if ($isChildOfFlier) {
$flierCategoryList[0]['category'] = $category['category'];
$flierCategoryList[0]['saleList'] = $this->getSaleRepository()->getActiveSalesByCategoryID($category['category']->getID());
$data['isChildOfFlier'] = true;
} else {
$i = 0;
/** @var MainMenu $flierMenuItem */
foreach ($flierMenu as $flierMenuItem) {
if ($selectedCity && count(array_intersect($selectedCity['entityList'], $category['entityList'])) == 0) {
continue;
}
$category = $this->getCategoryRepository()->findCached($flierMenuItem->getEntityID());
if ($category && $category['entityList'] && ($category['category']->getID() != Category::POPULAR_FLIER_CATEGORY_ID)) {
$flierCategoryList[$i]['category'] = $category['category'];
$flierCategoryList[$i]['saleList'] = $this->getSaleRepository()->getActiveSalesByCategoryID($category['category']->getID());
if (self::getMobileDevice($request)) {
$flierCategoryList[$i]['saleList'] = array_slice($flierCategoryList[$i]['saleList'], 0, 4);
}
$i++;
}
}
}
if ($selectedCity) {
foreach ($flierCategoryList as $key => $item) {
$saleListTemp = [];
foreach ($item['saleList'] as $sale) {
if (in_array($sale->getID(), $selectedCity['entityList'])) {
$saleListTemp[] = $sale;
}
}
$flierCategoryList[$key]['saleList'] = $saleListTemp;
$flierCategoryList[$key]['category']->setEntityCount(count($saleListTemp));
}
}
$data['flierMenu'] = $flierMenu;
$data['flierMenuCount'] = $flierMenuCount;
$data['flierCategoryList'] = $flierCategoryList;
$data['categoryList'] = $flierCategoryList;
$deviceType = self::getMobileDevice($request) ? self::DEVICE_TYPE_MOBILE : self::DEVICE_TYPE_DESKTOP;
$response = '';
if (self::getMobileDevice($request)) {
$response = $this->render('Slivki/mobile/sale/flier/index.html.twig', $data);
} else {
if ($isChildOfFlier && !$data['isChildOfFlier']) {
$response = $this->render('Slivki/sale/index.html.twig', $data);
} else {
$entityID = 0;
$entityTypeID = Visit::TYPE_FLIER_MAIN_PAGE;
if ($isChildOfFlier) {
$entityID = $category['category']->getID();
$entityTypeID = Visit::TYPE_FLIER_CATEGORY;
}
$this->addVisit($entityID, $entityTypeID, $deviceType, $this->getUser(), $request->getClientIp());
$response = $this->render('Slivki/sale/flier_index.html.twig', $data);
}
}
return $response;
}
public function detailsAction(
Request $request,
SaleCacheService $saleCacheService,
ServerFeatureStateChecker $serverFeatureStateChecker,
$entityID
) {
if (!$serverFeatureStateChecker->isServerFeatureEnabled(SwitcherFeatures::SALES())) {
return new Response('', Response::HTTP_NOT_FOUND);
}
$saleRepository = $this->getSaleRepository();
$preview = $request->query->get("preview", false);
$versionID = $request->query->get('version');
$sale = $saleCacheService->getSale($entityID, true);
if (!$sale || $preview) {
$sale = $this->getDoctrine()->getRepository(Sale::class)->find($entityID);
if (!$sale || ((!$sale->isActive() || !$sale->isInActivePeriod()) && !$preview)) {
throw $this->createNotFoundException("Sale $entityID not found");
}
}
$deviceType = self::getMobileDevice($request) ? self::DEVICE_TYPE_MOBILE : self::DEVICE_TYPE_DESKTOP;
$salesOffset = ['popular' => 0, 'new' => 0, 'extra' => 0];
$salesOffsetLastDate = $request->getSession()->get('sales-offset-last-date', null);
if ($salesOffsetLastDate != null && $salesOffsetLastDate >= (new \DateTime('-30 minutes'))) {
$salesOffsetSession = $request->getSession()->get('sales-offset', $salesOffset);
foreach ($salesOffset as $offsetKey => $offsetValue) {
if (isset($salesOffsetSession[$offsetKey])) {
$salesOffset[$offsetKey] = $salesOffsetSession[$offsetKey];
} else {
$offsetKey[$offsetKey] = 0;
}
}
}
$request->getSession()->set('sales-offset-last-date', (new \DateTime()));
$saleVersion = null;
if ($versionID) {
$saleVersion = $sale->getVersionByID($versionID);
} else {
$saleVersion = $sale->getCurrentVersion();
}
$isVideoguide = $sale->isVideoguide();
$isFlier = $sale->isFlier();
$data = [
'sale' => $sale,
'saleGeoLocationData' => $this->getSaleGeoLocationData($sale, $request->getPathInfo()),
'commentsAmount' => $this->getCommentRepository()->getCommentsCountByEntityID($entityID, Comment::TYPE_SALE_COMMENT),
'menuSelected' => MainMenu::MENU_ID_SALE,
'isFlier' => $isFlier,
'saleVersion' => $saleVersion
];
if (!$isVideoguide) {
$data['relatedSales'] = $saleCacheService->getRelatedSales($sale, $salesOffset);
}
$user = $this->getUser();
$entityManager = $this->getDoctrine()->getManager();
if ($user) {
$entityVote = $entityManager->getRepository(EntityVote::class)->findOneBy([
'entityID' => $sale->getID(),
'entityTypeID' => EntityVote::TYPE_SALE,
'user' => $user
]);
$data['userVote'] = 0;
if ($entityVote) {
$data['userVote'] = $entityVote->getVote();
}
}
$request->getSession()->set('sales-offset', $salesOffset);
$data['parentCategoryList'] = $this->getParentCategoryList($request, $sale->getDefaultCategoryID());
$data['offerRateSchedule'] = $this->getOfferRateSchedule($request->getSession());
$data['daysFromStart'] = $sale->getCreatedOn()->setTime(0, 0, 0)->diff(new \DateTime())->format('%a');
if ($data['daysFromStart'] > 45) {
$data['daysFromStart'] = 45;
}
if ($data['daysFromStart'] == 0) {
$data['daysFromStart'] = 1;
}
$data['director'] = null;
if ($sale->getDirectors()->count() > 0) {
$data['director'] = $sale->getDirectors()->first();
}
$data['descriptions'] = $this->renderView(CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/sale/sale_description_block.html.twig'
: 'Slivki/sale/sale_description_block.html.twig', [
'descriptions' => $this->getSaleDescriptionPortion($saleVersion)
]);
$view = 'Slivki/sale/sale.html.twig';
if (self::getMobileDevice($request)) {
$view = 'Slivki/mobile/sale/details.html.twig';
}
$visitCounterRepository = $entityManager->getRepository(VisitCounter::class);
$visitCounter = $visitCounterRepository->findBy(['type' => VisitCounter::TYPE_SALE, 'entityID' => $sale->getID()]);
$data['dayVisitCount'] = 0;
if ($isVideoguide) {
$authorCategory = $saleRepository->getVideoguideAutorCategory($sale);
if ($authorCategory) {
$categoryVisitCount = 0;
foreach ($saleRepository->getActiveSalesByCategoryID($authorCategory->getID()) as $saleItem) {
$categoryVisitCount += $visitCounterRepository->getVisitCount($saleItem->getID(), VisitCounter::TYPE_SALE, false);
}
$data['authorCategory'] = [
'category' => $authorCategory,
'visitCount' => $categoryVisitCount
];
}
$data['visitCount'] = 0;
if ($visitCounter) {
$data['visitCount'] = $visitCounter[0]->getVisitCount();
}
$session = $request->getSession();
if ($request->get('utm_source') != 'video_sidebar') {
$seenVideoguides = [$sale->getID()];
} else {
$seenVideoguides = $session->get('seenVideoguides', []);
$seenVideoguides[] = $sale->getID();
$seenVideoguides = array_unique($seenVideoguides);
}
$session->set('seenVideoguides', $seenVideoguides);
$data['seenVideoguides'] = json_encode($seenVideoguides);
$data['sidebarVideoguides'] = $this->getSidebarVideoguides($saleCacheService, $request, $sale->getID(), 0, 20);
$data['videoguideCategory'] = $this->getCategoryRepository()->findCached(Category::SALE_VIDEO_GUIDE_CATEGORY_ID);
$view = 'Slivki/sale/videoguide.html.twig';
if (self::getMobileDevice($request)) {
$view = 'Slivki/mobile/sale/videoguide/details.html.twig';
}
$this->addVisit($entityID, Visit::TYPE_SLIVKI_TV_GUIDES, $deviceType, $this->getUser(), $request->getClientIp());
} else {
$data['visitCount'] = $entityManager->getRepository(Visit::class)
->getVisitCount($sale->getID(), Category::SALE_CATEGORY_ID, $data['daysFromStart'], true);
if ($visitCounter) {
$data['dayVisitCount'] = $visitCounter[0]->getVisitCountRecent();
}
if ($sale->getID() == 253587) {
$data['visitCount'] += 10188;
}
}
if ($user && $user->hasRole(UserGroup::STATISTICS_VIEWER)) {
$data['yesterdayShareClicks'] = $this->getShareClicks($entityID);
}
$response = $this->render($view, $data);
if ($isFlier) {
$this->addVisit($entityID, Visit::TYPE_FLIER_DETAILS, $deviceType, $this->getUser(), $request->getClientIp());
}
$this->addVisit($entityID, Visit::TYPE_SALE, $deviceType, $this->getUser(), $request->getClientIp());
return $response;
}
public function getSaleGeoLocationData(Sale $sale, $saleURL) {
$features = [];
$saleID = $sale->getID();
foreach ($sale->getGeoLocations() as $geoLocation) {
$caption = $geoLocation->getStreet() . ', ' . $geoLocation->getHouse();
$features[] = [
'type' => 'Feature',
'id' => $geoLocation->getID(),
'geometry' => [
'type' => 'Point',
'coordinates' => [$geoLocation->getLatitude(), $geoLocation->getLongitude()]
],
'properties' => [
'iconClass' => 'always-caption',
'iconContent' => '',
'locationID' => $geoLocation->getID(),
'offerID' => $saleID,
'url' => $saleURL,
'hintContent' => $caption
]
];
}
$getLocationData = ['type' => 'FeatureCollection', 'features' => $features];
return json_encode($getLocationData);
}
/**
* @Route("/sales/get_descriptions/{saleID}/{saleVersionID}/{lastSortOrder}")
*/
public function getDescriptionsAction(Request $request, SaleCacheService $saleCacheService, $saleID, $saleVersionID, $lastSortOrder) {
$saleID = (int)$saleID;
$sale = $saleCacheService->getSale($saleID, true);
if (!$sale) {
$sale = $this->getDoctrine()->getRepository(Sale::class)->find($saleID);
if (!$sale) {
throw $this->createNotFoundException("Sale $saleID not found");
}
}
$saleVersion = $sale->getVersionByID($saleVersionID);
return $this->render(CommonUtil::isMobileDevice($request) ? 'Slivki/mobile/sale/sale_description_block.html.twig'
: 'Slivki/sale/sale_description_block.html.twig', [
'descriptions' => $this->getSaleDescriptionPortion($saleVersion, $lastSortOrder)
]);
}
private function getSaleDescriptionPortion($saleVersion, $lastSortOrder = -INF) {
$allDescriptions = $saleVersion->getAllDescriptions();
$result = [];
foreach ($allDescriptions as $description) {
if ($lastSortOrder >= $description->getSortOrder()) {
continue;
}
$result[] = $description;
if ($description instanceof SaleLoadMoreBtnDescription) {
break;
}
}
return $result;
}
/**
* @Route("/sales/get_more_videoguides/{saleID}/{offset}/{limit}")
*/
public function getMoreSidebarVideoguides(Request $request, SaleCacheService $saleCacheService, $saleID, $offset, $limit) {
$view = 'Slivki/sale/videoguide_sidebar_list.html.twig';
if (self::getMobileDevice($request)) {
$view = 'Slivki/mobile/sale/videoguide/next.html.twig';
}
return $this->render($view, [
'sidebarVideoguides' => $this->getSidebarVideoguides($saleCacheService, $request, $saleID, $offset, $limit)
]);
}
private function getSidebarVideoguides(SaleCacheService $saleCacheService, $request, $saleID, $offset = 0, $limit = 20) {
$session = $request->getSession();
$seenVideoguides = $session->get('seenVideoguides', []);
$topVideoguides = [];
if ($offset == 0) {
$sale = $this->getSaleRepository()->getActiveSaleByID($saleID);
if ($sale) {
$defaultCategoryID = $sale->getDefaultCategoryID();
if (!$defaultCategoryID) {
/** @var Category $category */
foreach ($sale->getCategories() as $category) {
if ($category->isChildOf(Category::SALE_VIDEO_GUIDE_CATEGORY_ID) && $category->getID() != Category::SALE_VIDEO_GUIDE_AUTORS_CATEGORY_ID) {
$defaultCategoryID = $category->getID();
break;
}
}
}
if ($defaultCategoryID) {
$topVideoguides = $this->getSaleRepository()->getActiveSalesByCategoryID($defaultCategoryID);
$implodedIDs = '';
foreach ($topVideoguides as $key => $videoguide) {
if (!in_array($videoguide->getID(), $seenVideoguides)) {
$implodedIDs .= $sale->getID() . ',';
} else {
unset($topVideoguides[$key]);
}
}
$implodedIDs = trim($implodedIDs, ',');
if ($implodedIDs != '') {
$sql = 'select entity_id, visit_count from visit_count_aggregated where entity_id in (' . $implodedIDs . ') and days_count = 7';
$result = $this->getDoctrine()->getManager()->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_ASSOC);
$visitCountList = [];
foreach ($result as $item) {
$visitCountList[$item['entity_id']] = $item['visit_count'];
}
usort($topVideoguides, function ($sale, $sale1) use (&$visitCountList) {
$visitCount = isset($visitCountList[$sale->getID()]) ? $visitCountList[$sale->getID()] : 0;
$visitCount1 = isset($visitCountList[$sale1->getID()]) ? $visitCountList[$sale1->getID()] : 0;
if ($visitCount == $visitCount1) {
return $sale->getID() > $sale1->getID() ? -1 : 1;
}
return $visitCount > $visitCount1 ? -1 : 1;
});
$topVideoguides = array_slice($topVideoguides, 0, 3);
foreach ($topVideoguides as $videoguide) {
$seenVideoguides[] = $videoguide->getID();
}
}
}
}
}
$allVideoguides = $saleCacheService->getSalesByCategoryID(Category::SALE_VIDEO_GUIDE_CATEGORY_ID);
if (count($allVideoguides) == 0) {
return [];
}
$implodedIDs = '';
foreach ($allVideoguides as $key => $sale) {
if (!in_array($sale->getID(), $seenVideoguides)) {
$implodedIDs .= $sale->getID() . ',';
} else {
unset($allVideoguides[$key]);
}
}
$implodedIDs = trim($implodedIDs, ',');
$sql = 'select entity_id, visit_count from visit_count_aggregated where entity_id in (' . $implodedIDs . ') and days_count = 7';
$result = $this->getDoctrine()->getManager()->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_ASSOC);
$visitCountList = [];
foreach ($result as $item) {
$visitCountList[$item['entity_id']] = $item['visit_count'];
}
usort($allVideoguides, function ($sale, $sale1) use (&$visitCountList) {
$visitCount = isset($visitCountList[$sale->getID()]) ? $visitCountList[$sale->getID()] : 0;
$visitCount1 = isset($visitCountList[$sale1->getID()]) ? $visitCountList[$sale1->getID()] : 0;
if ($visitCount == $visitCount1) {
return $sale->getID() > $sale1->getID() ? -1 : 1;
}
return $visitCount > $visitCount1 ? -1 : 1;
});
$result = array_slice($allVideoguides, $offset, $limit);
if ($offset == 0) {
$result = array_merge($topVideoguides, $result);
}
return $result;
}
/** @Route("/sale/filter/map/{categoryID}") */
public function mapFilterAction(Request $request, $categoryID) {
$offerIDList = $request->request->get('offerList', []);
$offerIDFiltered = $offerIDList;
$category = null;
if ($categoryID > 0) {
$category = $this->getDoctrine()->getRepository(Category::class)->findCached($categoryID);
$offerList = $this->getDoctrine()->getRepository(Category::class)->getActiveEntityListByCategory($categoryID);
$offerIDFiltered = [];
foreach ($offerList as $offer) {
if (in_array($offer->getID(), $offerIDList)) {
$offerIDFiltered[] = $offer->getID();
}
}
}
$flierCategory = false;
$cacheName = OfferRepository::CACHE_NAME_TEASERS;
if ($category && ($categoryID == Category::FLIER_SALE_CATEGORY_ID || $category['category']->isChildOf(Category::FLIER_SALE_CATEGORY_ID))) {
$cacheName = SaleRepository::CACHE_NAME_TEASERS_FLIER;
$flierCategory = true;
}
$teasersCache = new SoftCache($cacheName);
$teaserList = $teasersCache->getMulti($offerIDFiltered);
$result = ['html' => '', 'count' => 0];
if ($teaserList) {
$html = '';
if ($categoryID == Category::FLIER_SALE_CATEGORY_ID) {
$html = implode('', $teaserList);
} else {
$html = $this->get('twig')->render('Slivki/sale/teasers.html.twig', ['teaserList' => $teaserList]);
$html = '<div class="sale-list-box map-filtered-list"><div class="sale-list-box-table"><div class="table-item sales-list"><ul class="table-item-list">' . $html . '</ul></div></div></div>';
}
$result = [
'html' => $html,
'count' => count($teaserList),
'flierCategory' => $flierCategory
];
}
return new JsonResponse($result);
}
/** @Route("/sale/location-info/{categoryID}/{limit}/{offset}") */
public function getLocationInfoAction($categoryID, $limit, $offset) {
$saleGeoLocationCache = new SoftCache(SaleRepository::CACHE_NAME_GEO_LOCATION_DATA);
$features = $saleGeoLocationCache->get($categoryID, []);
if (!$features) {
$features = [];
}
$features = array_slice($features, $offset, $limit);
if (empty($features)) {
return new Response(json_encode([]));
}
$getLocationData = ['type' => 'FeatureCollection', 'features' => $features];
return new Response(json_encode($getLocationData));
}
/** @Route("/profile/vote_sale/{saleID}/{vote}") */
public function voteSaleAction($saleID, $vote) {
$user = $this->getUser();
$entityManager = $this->getDoctrine()->getManager();
$entityVote = $entityManager->getRepository(EntityVote::class)->findOneBy([
'entityID' => $saleID,
'entityTypeID' => EntityVote::TYPE_SALE,
'user' => $user
]);
if (!$entityVote) {
$entityVote = new EntityVote();
$entityVote->setEntityID($saleID);
$entityVote->setCreatedOn(new \DateTime());
$entityVote->setUser($user);
$entityVote->setEntityTypeID(EntityVote::TYPE_SALE);
$entityManager->persist($entityVote);
}
$entityVote->setLastModified(new \DateTime());
$entityVote->setVote($vote);
$entityManager->flush();
return new JsonResponse($entityManager->getRepository(Comment::class)->getEntityRatingWithCount(Category::SALE_CATEGORY_ID, $saleID));
}
/** @Route("/listovki", name = "flierLanding") */
public function hyperShopAction(
Request $request,
SaleCacheService $saleCacheService,
ServerFeatureStateChecker $serverFeatureStateChecker
) {
if (!$serverFeatureStateChecker->isServerFeatureEnabled(SwitcherFeatures::FLIERS())) {
return new Response('', Response::HTTP_NOT_FOUND);
}
$productLength = 5;
$data = [];
$entityManager = $this->getDoctrine()->getManager();
$saleProductRepository = $entityManager->getRepository(SaleProduct::class);
$saleRepository = $this->getSaleRepository();
$softCache = new SoftCache(SaleRepository::CACHE_NAME);
$data['menuSelected'] = MainMenu::MENU_ID_FLIER;
$data['saleVisitCount'] = $softCache->get(SaleRepository::FLIER_VISIT_COUNT_CACHE_KEY);
$data['visitedSales'] = $softCache->get(SaleRepository::VISITED_FLIER_COUNT_CACHE_KEY);
$data['saleVisitCountTooltip'] = 'Количество читателей раздела "Листовки" за 30 дней';
$data['visitedSalesTooltip'] = 'Количество прочитанных листовок за 30 дней';
$fliers = $saleCacheService->getSalesByCategoryID(Category::POPULAR_FLIER_CATEGORY_ID);
$data['fliersCount'] = count($fliers);
$fliersSliderData = '';
$isMobileDevice = self::getMobileDevice($request);
$view = $isMobileDevice ? 'Slivki/mobile/sale/flier/teaser.html.twig' : 'Slivki/sale/flier.html.twig';
foreach (array_slice($fliers, 0, 10) as $sale) {
$fliersSliderData .= $this->renderView($view, ['sale' => $sale, 'additionalClass' => 'swiper-slide']);
}
$data['fliersSliderData'] = $fliersSliderData;
$saleProductList = $saleRepository->getSaleProductsCached();
$foodProductListID = $saleRepository->getSaleProductsIDByCategoryID(Category::FOOD_SALE_CATEGORY_ID);
$foodProductListID = array_slice(array_reverse($foodProductListID), 0, $productLength);
$data['saleProductList'] = [];
foreach ($foodProductListID as $productID) {
$data['saleProductList'][] = $saleProductRepository->find($productID);
}
$data['productCount'] = count($data['saleProductList']);
$mainMenuRepository = $entityManager->getRepository(MainMenu::class);
$flierMenu = $mainMenuRepository->getItemListCached(MainMenu::MENU_ID_FLIER, City::DEFAULT_CITY_ID);
$flierMenuCount = 0;
$cityName = $request->query->get('city');
$selectedCity = null;
if ($cityName) {
$cityList = $softCache->get(SaleRepository::CITIES_CACHE_KEY);
foreach ($cityList as $item) {
$firstChar = mb_substr($cityName, 0, 1);
if (isset($cityList[$firstChar])) {
foreach ($cityList[$firstChar] as $city) {
if ($city['cityName'] == $cityName) {
$selectedCity = $city;
$data['selectedCity'] = $cityName;
break;
}
}
}
}
}
$flierMenuTemp = [];
foreach ($flierMenu as $flierMenuItem) {
if (in_array($flierMenuItem->getType(), [MainMenu::TYPE_OFFER_CATEGORY, MainMenu::TYPE_SALE_CATEGORY])) {
$flierCategory = $this->getCategoryRepository()->findCached($flierMenuItem->getEntityID());
if ($flierCategory) {
$entityCount = 0;
if ($selectedCity) {
$entityCount = count(array_unique(array_intersect($selectedCity['entityList'], $flierCategory['entityList'])));
} else {
$entityCount = $flierCategory['category']->getEntityCount();
}
if ($entityCount > 0) {
$flierMenuItem->setEntityCount($entityCount);
$flierMenuCount += $entityCount;
$flierMenuTemp[] = $flierMenuItem;
}
}
}
}
$flierMenu = $flierMenuTemp;
$cityList = $softCache->get(SaleRepository::CITIES_CACHE_KEY);
$data['cityList'] = $cityList ? $cityList : [];
$flierCategoryList = [];
$i = 0;
/** @var MainMenu $flierMenuItem */
foreach ($flierMenu as $flierMenuItem) {
$category = $this->getCategoryRepository()->findCached($flierMenuItem->getEntityID());
if (!isset($category['entityList']) || ($selectedCity && count(array_intersect($selectedCity['entityList'], $category['entityList'])) == 0)) {
continue;
}
if ($category && $category['entityList'] && ($category['category']->getID() != Category::POPULAR_FLIER_CATEGORY_ID)) {
$flierCategoryList[$i]['category'] = $category['category'];
$flierCategoryList[$i]['saleList'] = $saleCacheService->getSalesByCategoryID($category['category']->getID());
if (self::getMobileDevice($request)) {
$flierCategoryList[$i]['saleList'] = array_slice($flierCategoryList[$i]['saleList'], 0, 4);
}
$i++;
}
}
if ($selectedCity) {
foreach ($flierCategoryList as $key => $item) {
$saleListTemp = [];
foreach ($item['saleList'] as $sale) {
if (in_array($sale->getID(), $selectedCity['entityList'])) {
$saleListTemp[] = $sale;
}
}
$flierCategoryList[$key]['saleList'] = $saleListTemp;
$flierCategoryList[$key]['category']->setEntityCount(count($saleListTemp));
}
}
$data['flierCategoryList'] = $flierCategoryList;
$view = $isMobileDevice ? 'Slivki/mobile/sale/flier/hyper_shop.html.twig' : 'Slivki/sale/hyper_shop.html.twig';
return $this->render($view, $data);
}
/** @Route("/new-hyper-shop/more/{offset}/{limit}") */
public function hyperShopMoreAction(Request $request, $limit, $offset) {
$fliers = $this->getSaleRepository()->getActiveSalesByCategoryID(Category::FLIER_SALE_CATEGORY_ID);
$result = '';
$view = self::getMobileDevice($request) ? 'Slivki/mobile/sale/flier/teaser.html.twig' : 'Slivki/sale/flier.html.twig';
foreach (array_slice($fliers, $offset, $limit) as $sale) {
$result .= $this->renderView($view, ['sale' => $sale, 'additionalClass' => 'swiper-slide']);
}
return new Response($result);
}
}