<?php
namespace Slivki\EventSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use Slivki\Controller\SiteController;
use Slivki\Entity\MailingCampaign;
use Slivki\Entity\MailingStatistic;
use Slivki\Entity\Seo;
use Slivki\Entity\User;
use Slivki\Enum\Order\Domain;
use Slivki\Services\City\CityCacheService;
use Slivki\Services\City\CityProvider;
use Slivki\Services\MailingCampaign\Partner\PartnerMailingCampaignClickHandler;
use Slivki\Util\CommonUtil;
use Slivki\Entity\City;
use Slivki\Util\Iiko\BurgerKing;
use Slivki\Util\Iiko\Crabs;
use Slivki\Util\Iiko\DinnerBuffet;
use Slivki\Util\Iiko\Dodo;
use Slivki\Util\Iiko\Dominos;
use Slivki\Util\Iiko\PirogiBy;
use Slivki\Util\Iiko\Pirogovaya1;
use Slivki\Util\Iiko\Shtolle;
use Slivki\Util\Iiko\SushiChefArts;
use Slivki\Util\Iiko\SushiVesla;
use Slivki\Util\Iiko\Urbanfood;
use Slivki\Util\Iiko\WokiToki;
use Slivki\Util\SoftCache;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
final class KernelControllerSubscriber implements EventSubscriberInterface
{
private const PATTERNS_FOR_NOT_REDIRECT = [
'delivery',
'gift-certificate',
'login',
'api/online-order/',
];
private array $allowedSubdomains = [
'tokiny',
'sushihouse',
'm',
'marketplace',
'okpirog',
SushiChefArts::DOMAIN,
'citysushi',
'tuna',
'fsushi',
'moresushi',
'73',
WokiToki::DOMAIN,
DinnerBuffet::DOMAIN,
Dominos::DOMAIN,
'sushi-master',
'mp',
PirogiBy::DOMAIN,
Pirogovaya1::DOMAIN,
BurgerKing::DOMAIN,
Crabs::DOMAIN,
'deka',
Shtolle::DOMAIN,
Dodo::DOMAIN,
'whitelotus',
'marsel',
'shah',
'avokado',
'express-pizza',
'heropark',
'thesushi',
SushiVesla::DOMAIN,
Urbanfood::DOMAIN,
'profisushi',
'artsushi',
'byrolls',
'ajia',
'jasmin',
'ustrica',
'pastadeli',
Domain::OUSHEN,
'sea',
'wineseafood',
'izumi',
'delyga',
'zhanchay',
'sushimaster',
Domain::TOKIO_SUSHI,
Domain::MEGASUN,
];
private array $placeHolderDomains = [];
private $baseDomain;
private EntityManagerInterface $entityManager;
private CityCacheService $cityCacheService;
private PartnerMailingCampaignClickHandler $partnerMailingCampaignClickHandler;
private CityProvider $cityProvider;
public function __construct(
EntityManagerInterface $entityManager,
CityCacheService $cityCacheService,
PartnerMailingCampaignClickHandler $partnerMailingCampaignClickHandler,
CityProvider $cityProvider,
string $baseDomain
) {
$this->baseDomain = $baseDomain;
$this->entityManager = $entityManager;
$this->cityCacheService = $cityCacheService;
$this->partnerMailingCampaignClickHandler = $partnerMailingCampaignClickHandler;
$this->cityProvider = $cityProvider;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => ['onKernelRequest', 33],
KernelEvents::RESPONSE => ['onKernelResponse', 33]
];
}
public function onKernelRequest(RequestEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
$pathInfo = $request->getPathInfo();
$hostExploded = explode('.', $request->getHost());
$subDomain = $hostExploded[0];
if ($subDomain === 'delyga') {
return;
}
if (\in_array($subDomain, $this->allowedSubdomains, true) && !$this->isIncludedToRoute($pathInfo)) {
$event->setResponse(new RedirectResponse(
\sprintf(
'https://%s%s%s',
$request->getSession()->get(City::CITY_DOMAIN_SESSION_KEY, 'www'),
$this->baseDomain,
$pathInfo,
),
Response::HTTP_TEMPORARY_REDIRECT,
));
return;
}
$cityID = $this->cityProvider->getDefaultCityId();
$request->getSession()->set(City::CITY_ID_SESSION_KEY, $cityID);
if (!in_array($subDomain, $this->allowedSubdomains, true)) {
if ('' !== $subDomain && 'www' !== $subDomain) {
$subDomainCityId = $this->cityCacheService->getCityIdByDomain($subDomain);
if (null === $subDomainCityId) {
$event->setResponse(new RedirectResponse($this->baseDomain . $pathInfo, 302));
} else {
$cityID = $subDomainCityId;
}
}
$request->getSession()->set(City::CITY_ID_SESSION_KEY, $cityID);
$request->getSession()->set(City::CITY_DOMAIN_SESSION_KEY, $subDomain);
if (City::DEFAULT_CITY_ID === $cityID && 'www' !== $subDomain) {
$event->setResponse(new RedirectResponse('https://www' . $this->baseDomain, 301));
return;
}
}
$this->saveMailingStatistic($request);
$this->partnerMailingCampaignClickHandler->handle($request);
$seoRepository = $this->entityManager->getRepository(Seo::class);
$metaInfo = $seoRepository->getByAlias($pathInfo, $subDomain, $this->baseDomain);
if (isset($this->placeHolderDomains[$subDomain])) {
$request->attributes->set('_controller', "Slivki\\Controller\\DefaultController::domainPlaceHolderAction");
$request->attributes->set("entityID", $this->placeHolderDomains[$subDomain]);
return;
}
if ($metaInfo && $metaInfo != SoftCache::EMPTY_VALUE) {
$exploded = explode(':', $metaInfo->getResourceURL());
$url = "Slivki\\Controller\\" . $exploded[1] . "Controller::" . $exploded[2] . 'Action';
$request->attributes->set('_controller', $url);
$request->attributes->set("entityID", $metaInfo->getEntityID());
$request->attributes->set(SiteController::PARAMETER_META_INFO, $metaInfo);
if (!$metaInfo->isActive() && !in_array($subDomain, $this->allowedSubdomains)) {
$redirectURL = $metaInfo->getRedirectURL();;
if ($request->query->count()) {
$parameters = [];
foreach ($request->query->all() as $key => $value) {
$parameters[] = $key . '=' . $value;
}
$redirectURL .= '?' . implode('&', $parameters);
}
$event->setResponse(new RedirectResponse($redirectURL, 301));
}
}
}
public function onKernelResponse(ResponseEvent $event) {
$refID = $event->getRequest()->query->get('ref');
if ($refID) {
$cookie = Cookie::create('refID', $refID, new \DateTime('+1 month'));
$event->getResponse()->headers->setCookie($cookie);
}
}
private function saveMailingStatistic(Request $request) {
$query = $request->query;
$mailingCampaignID = $query->getInt('utm_campaign');
$userID = $query->getInt('utm_b');
$entityID = $query->getInt('utm_c');
$entityType = $query->getInt('utm_d');
$entityManager = $this->entityManager;
// Рассылка с бонусом для Могилева
if ($mailingCampaignID == 1041 && $userID) {
$user = $entityManager->find(User::class, $userID);
if (!$user) {
return;
}
if ($entityManager->getRepository(User::class)->setMogilevMailingBonus($user)) {
$request->getSession()->getFlashBag()->add('showMogilevMailingBonusPopup', '1');
}
return;
}
// Рассылка с бонусом для Гомеля
if ($mailingCampaignID == 1042 && $userID) {
$user = $entityManager->find(User::class, $userID);
if (!$user) {
return;
}
if ($entityManager->getRepository(User::class)->setGomelMailingBonus($user)) {
$request->getSession()->getFlashBag()->add('showMogilevMailingBonusPopup', '1');
}
return;
}
if (!$mailingCampaignID || !$entityType || !$entityID) {
return;
}
$mailingCampaign = $entityManager->find(MailingCampaign::class, $mailingCampaignID);
if (!$mailingCampaign) {
return;
}
$mailingStatistic = new MailingStatistic();
$mailingStatistic->setMobileVersion(CommonUtil::isMobileDevice($request));
$user = null;
if ($userID) {
$user = $entityManager->find(User::class, $userID);
if ($user) {
$mailingStatistic->setUser($user);
}
}
$mailingStatistic->setIpAddress($request->getClientIp());
$mailingStatistic->setMailingCampaign($mailingCampaign);
$mailingStatistic->setEntityID($entityID);
$mailingStatistic->setEntityType($entityType);
$entityManager->persist($mailingStatistic);
$entityManager->flush();
}
private function isIncludedToRoute(string $pathInfo): bool
{
$matches = \array_filter(
self::PATTERNS_FOR_NOT_REDIRECT,
static fn(string $needle): bool => false !== strpos($pathInfo, $needle),
);
return 0 < \count($matches);
}
}