<?php
namespace App\EventListener;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Router;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\VarDumper\VarDumper;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use App\Entity\Redirection;
use App\Entity\User;
use App\Service\FacebookConversion;
class RequestListener implements EventSubscriberInterface
{
private $em;
private $router;
private $client;
private $params;
private $fbConversion;
public function __construct(RouterInterface $router, EntityManagerInterface $em, HttpClientInterface $client, ParameterBagInterface $params, FacebookConversion $fbConversion)
{
$this->router = $router;
$this->em = $em;
$this->client = $client;
$this->params = $params;
$this->fbConversion = $fbConversion;
}
public static function getSubscribedEvents(): array
{
return [
ExceptionEvent::class => 'onException',
RequestEvent::class => 'onRequest',
];
}
public function onException(RequestEvent $event)
{
if ($event->getRequest()->getRequestUri()) {
if ($event->getThrowable() instanceof NotFoundHttpException) {
$code = "404";
} else {
$code = "500";
}
$redirections = $this->em->getRepository("App:Redirection")->findBy(['path' => $event->getRequest()->getRequestUri(), 'deletedAt' => null]);
if (count($redirections) <= 0) {
$redirection = new Redirection();
$redirection->setPath($event->getRequest()->getRequestUri());
$redirection->setCode($code);
$this->em->persist($redirection);
$this->em->flush();
} else {
$target = null;
foreach ($redirections as $redirection) {
if ($redirection->getTarget()) {
$target = $redirection->getTarget();
}
}
if ($target !== null) {
$response = new RedirectResponse($redirection->getTarget(), Response::HTTP_MOVED_PERMANENTLY);
$event->setResponse($response);
}
}
}
}
private function fetchUsersLocationFromIp(string $ip): ?array
{
try {
$response = $this->client->request('GET', 'https://ipinfo.io/' . $ip . '/json?token=' . $this->params->get('ipinfo_token'));
if ($response->getStatusCode() === 200) {
$res = $response->toArray();
if (!isset($res['country']) || !isset($res['timezone'])) {
return null;
}
return $response->toArray();
}
} catch (\Exception $e) {
return null;
}
return null;
}
private function getCurrencyFromIp(string $ip): string
{
$location = $this->fetchUsersLocationFromIp($ip);
if (!$location) {
return 'euros';
}
if ($location['country'] === 'FR') {
return 'euros';
} else if ($location['country'] === 'GB') {
return 'pounds';
}
if (strpos($location['timezone'], 'Europe') === false) {
return 'dollars';
}
return 'euros';
}
public function onRequest(RequestEvent $event)
{
$userAgent = $event->getRequest()->headers->get('User-Agent');
if (preg_match('/googlebot|bingbot|slurp|duckduckbot|baiduspider|yandex|uptimerobot/i', $userAgent)) {
return;
}
// do not redirect if the request is for an API endpoint or the admin panel
if (str_starts_with($event->getRequest()->getRequestUri(), '/api') || str_starts_with($event->getRequest()->getRequestUri(), '/admin')) {
return;
}
if ($event->isMainRequest()) {
$session = $event->getRequest()->getSession();
if($event->getRequest()->get('selected_locale')){
$session->set('selected_locale', $event->getRequest()->get('selected_locale'));
}
// if (!$session->has('uniqSessionId')) {
// $session->set('uniqSessionId', $session->getId().'_'.uniqid());
// }
if ($event->getRequest()->get('fbclid')){
$session->set('fbclid', $this->fbConversion->makeFBCID($event->getRequest()->get('fbclid')));
}
if ($event->getRequest()->get('rdt_cid')){
$session->set('rdt_cid', $event->getRequest()->get('rdt_cid'));
}
if ($event->getRequest()->get('selected_currency')){
$allowedCurrencies = ['euros', 'dollars', 'pounds'];
$selectedCurrency = $event->getRequest()->get('selected_currency');
if (in_array($selectedCurrency, $allowedCurrencies) && $selectedCurrency !== $session->get('currency')) {
$session->set('currency', $selectedCurrency);
$session = $event->getRequest()->getSession();
$repoCart = $this->em->getRepository('App:Cart');
$cart = $repoCart->findOneBy(array(
"session" => User::getSessionId($event->getRequest()),
"ordered" => false
));
if ($cart) {
foreach ($cart->getCartProducts() as $cartProduct) {
$this->em->remove($cartProduct);
}
$this->em->remove($cart);
$this->em->flush();
}
}
}
if (!$session->get('currency')) {
$userIp = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
$session->set('currency', $this->getCurrencyFromIp($userIp));
}
$browserLocale = $event->getRequest()->getPreferredLanguage(array('en', 'fr'));
$targetLocale = $session->has('selected_locale') ? $session->get('selected_locale') : $browserLocale;
if ($event->getRequest()->getLocale() != $targetLocale) {
$route = $this->router->match($event->getRequest()->getPathInfo());
if(array_key_exists('_route', $route)){
$attributes = $route;
unset($attributes['_route']);
unset($attributes['_controller']);
$attributes['_locale'] = $targetLocale;
$response = new RedirectResponse($this->router->generate($route["_route"], $attributes));
$event->getRequest()->setLocale($targetLocale);
$event->setResponse($response);
}
}
}
}
}