<?php
namespace App\EventListener;
use App\Application\Service\Api\Service\FileService;
use App\Application\Service\Session\SessionService;
use App\Controller\Front\Account\AccountCreationController;
use App\Entity\System\Catalog;
use App\Entity\System\Customer;
use App\Entity\System\Employee;
use App\Service\EnvironmentService;
use Request as LegacyRequest;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Security;
class LegacyBootstrapListener
{
public const CONTOLLERS_CHECKOUT = ['cartController', 'subscriptionController'];
public const METHOD_CHECKOUT = ['checkout', 'mobilecart'];
public const LINKS_CHECKOUTS = ['/cart/checkout', 'subscription/checkout', 'cart/mobileCart'];
private RequestStack $requestStack;
private UrlGeneratorInterface $urlGenerator;
private Security $security;
private RouterInterface $router;
private EnvironmentService $environmentService;
private string $legacyDir;
private SessionService $sessionService;
public function __construct(
RequestStack $requestStack,
UrlGeneratorInterface $urlGenerator,
Security $security,
RouterInterface $router,
EnvironmentService $environmentService,
FileService $fileService,
SessionService $sessionService
) {
$this->requestStack = $requestStack;
$this->urlGenerator = $urlGenerator;
$this->security = $security;
$this->router = $router;
$this->legacyDir = $fileService->getLegacyDir();
$this->environmentService = $environmentService;
$this->sessionService = $sessionService;
}
public function onKernelRequest(RequestEvent $event): void
{
if ($this->environmentService->isApi()) {
return;
}
$symfonyRequest = $event->getRequest();
$refTapfiliate = $symfonyRequest->query->get('ref');
$this->requestStack->getSession()->set('isCheckout', false);
try {
$pathInfo = $this->router->match($event->getRequest()->getPathInfo());
} catch (ResourceNotFoundException $exception) {
return;
}
$this->defineLayoutsPath($event->getRequest()->getPathInfo());
if (
\array_key_exists('_route', $pathInfo)
&& ($pathInfo['_route'] === 'legacy_front_endpoints'
|| $pathInfo['_route'] === 'legacy_service_endpoints'
|| $pathInfo['_route'] === 'legacy_admin_endpoints')
) {
$legacyRequest = new LegacyRequest(); // TODO move logic inside LegacyRequest here
$controller = $legacyRequest->getControlador().LegacyRequest::DEFAULT_NAME_CONTROLLER;
$method = $legacyRequest->getMetodo();
$args = $legacyRequest->getArgumentos();
$this->sessionService->set('controller', $controller);
$this->sessionService->set('metodo', $method);
$this->sessionService->set('argumentos', $args);
$this->sessionService->set('url', $legacyRequest->getUrl());
if (!$this->sessionService->get(SessionService::ALLOWED_CATALOGS_KEY) || empty($this->sessionService->get(SessionService::ALLOWED_CATALOGS_KEY))) {
$this->sessionService->set(SessionService::ALLOWED_CATALOGS_KEY, [Catalog::DEFAULT_CATALOG_BIGBUY_REFERENCE]);
}
$resolvedController = $this->resolveLegacyController($legacyRequest, $controller, $method, $args);
$this->saveGoogleAnalyticsCookie($legacyRequest, $resolvedController['class']);
$symfonyRequestData = $symfonyRequest->request->get('legacy_controller');
$symfonyRequest->request->set('legacy_controller', [
'url' => $legacyRequest->getUrl(),
'controller' => $resolvedController['class'],
'method' => $resolvedController['method'],
'args' => $resolvedController['args'],
]);
if (
$symfonyRequestData !== null
&& !\array_key_exists('ref', $symfonyRequestData)
&& empty($symfonyRequestData['ref'])
&& $refTapfiliate !== null
) {
$symfonyRequest->request->set('legacy_controller', [
'url' => $legacyRequest->getUrl(),
'controller' => $resolvedController['class'],
'method' => $resolvedController['method'],
'args' => $resolvedController['args'],
'ref' => $refTapfiliate,
]);
}
$this->populateSfSessionFromSessionGlobal($symfonyRequest->getSession());
if (in_array($controller, self::CONTOLLERS_CHECKOUT) && in_array($method, self::METHOD_CHECKOUT)) {
$this->requestStack->getSession()->set('isCheckout', true);
}
}
$this->checkCustomerPartialAccountAndRedirect($event);
}
/**
* @param string $path
* @param string $controller
*
* @return string
*/
private function getLegacyControllerPath(string $path, string $controller): string
{
return $this->legacyDir.'/controllers'.DIRECTORY_SEPARATOR.$path.DIRECTORY_SEPARATOR.$controller.'.php';
}
/**
* @param LegacyRequest $legacyRequest
* @param string $controller
* @param string $method
* @param array $args
*
* @return array
*/
private function resolveLegacyController(LegacyRequest $legacyRequest, string $controller, string $method, array $args): array
{
if ($legacyRequest->getAdmin()) {
$path = ADMIN_DIR;
} elseif ($legacyRequest->getService()) {
$path = SERVICE_DIR;
} else {
$path = FRONT_DIR;
}
$rutaControlador = $this->getLegacyControllerPath($path, $controller);
$maintenanceips = explode(';', \Configuration::get('MAINTENANCE_IPS', true));
$realIP = '';
if (isset($_SERVER['HTTP_X_REAL_IP'])) {
$realIP = $_SERVER['HTTP_X_REAL_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$realIP = $_SERVER['REMOTE_ADDR'];
}
if (!empty($args) && $legacyRequest->getService()) {
$args = $this->sessionService->get('argumentos');
}
if (\Configuration::get('MAINTENANCE') !== '0' && !in_array($realIP, $maintenanceips)) {
return [
'class' => LegacyRequest::MAINTENANCE_CONTROLLER,
'method' => LegacyRequest::DEFAULT_METHOD,
'args' => $args,
];
// throw new ServiceUnavailableHttpException();
}
if (!is_callable([$controller, $method]) || !is_readable($rutaControlador)) {
return [
'class' => LegacyRequest::NOT_FOUND_CONTROLLER,
'method' => LegacyRequest::DEFAULT_METHOD,
'args' => $args,
];
// throw new NotFoundHttpException('Not Found');
}
// Require requested controller and all the rest from the same folder (service, admin, front..) because in certain cases a controller calls another...
// Sort descending because of a single case (admin/sliderController must be loaded before admin/bannerController). So dirty, I know.
foreach (scandir($this->legacyDir.'/controllers'.DIRECTORY_SEPARATOR.$path, SCANDIR_SORT_DESCENDING) as $filename) {
$controllerPath = $this->legacyDir.'/controllers'.DIRECTORY_SEPARATOR.$path.'/'.$filename;
if (is_file($controllerPath) && strpos($filename, 'Controller')) {
require_once $controllerPath;
}
}
return [
'class' => $controller,
'method' => $method,
'args' => $args,
];
}
private function saveGoogleAnalyticsCookie(LegacyRequest $legacyRequest, string $class): void
{
if (
LegacyRequest::NOT_FOUND_CONTROLLER !== $class && LegacyRequest::MAINTENANCE_CONTROLLER !== $class
&& $legacyRequest->getFront() && !\Tools::getValue('ajax')
) {
\GACookie::SaveCookie();
}
}
private function populateSfSessionFromSessionGlobal(SessionInterface $session): void
{
foreach ($_SESSION as $key => $value) {
if ($key !== '_sf2_attributes') {
$session->set($key, $value);
}
}
}
/**
* @param RequestEvent $requestEvent
*
* @return void
*/
private function checkCustomerPartialAccountAndRedirect(RequestEvent $requestEvent): void
{
if (Request::METHOD_OPTIONS === $requestEvent->getRequest()->getMethod()) {
return;
}
$pathInfo = $requestEvent->getRequest()->getPathInfo();
/** @var Customer|null $customer */
$customer = $this->security->getUser();
if ($customer instanceof Employee) {
return;
}
$this->checkLinksCheckouts($pathInfo, $customer, $requestEvent);
}
private function checkLinksCheckouts(string $pathInfo, ?Customer $customer, RequestEvent $requestEvent): void
{
foreach (self::LINKS_CHECKOUTS as $path) {
if (str_contains($pathInfo, $path)) {
$this->checkPartialCreation($customer, $requestEvent, $pathInfo);
}
}
}
private function checkPartialCreation(?Customer $customer, RequestEvent $requestEvent, string $pathInfo): void
{
if (!$customer) {
return;
}
switch ($customer->getPartialCreation()) {
case Customer::PARTIAL_CREATION_STEP_0:
$requestEvent->setResponse(new RedirectResponse($this->urlGenerator->generate('account_creation_step1', [], UrlGeneratorInterface::ABSOLUTE_URL)));
$this->requestStack->getSession()->set(AccountCreationController::ACCOUNT_CREATION_REDIRECT, $pathInfo);
return;
case Customer::PARTIAL_CREATION:
$requestEvent->setResponse(new RedirectResponse($this->urlGenerator->generate('account_creation_step2', [], UrlGeneratorInterface::ABSOLUTE_URL)));
$this->requestStack->getSession()->set(AccountCreationController::ACCOUNT_CREATION_REDIRECT, $pathInfo);
break;
}
}
private function defineLayoutsPath(string $route): void
{
$templateDir = FRONT_DIR;
if (preg_match('/^\/'.ADMIN_DIR.'\//', $route, $m)) {
$templateDir = ADMIN_DIR;
if (!defined('IS_ADMIN')) {
define('IS_ADMIN', '1');
}
} // SI ESTAMOS EN SERVICE
elseif (preg_match('/^\/'.SERVICE_DIR.'\//', $route, $m)) {
$templateDir = SERVICE_DIR;
if (!defined('IS_SERVICE')) {
define('IS_SERVICE', '1');
}
}
if (!defined('LAYOUTS_PATH')) {
/** @phpstan-ignore-next-line */
define('LAYOUTS_PATH', (IS_MOBILE ? MOBILE_VIEWS.DIRECTORY_SEPARATOR : '').$templateDir.DIRECTORY_SEPARATOR.'layout'.DIRECTORY_SEPARATOR);
}
if (!defined('PARTIALS_PATH')) {
/** @phpstan-ignore-next-line */
define('PARTIALS_PATH', (IS_MOBILE ? MOBILE_VIEWS.DIRECTORY_SEPARATOR : '').$templateDir.DIRECTORY_SEPARATOR.'partial'.DIRECTORY_SEPARATOR);
}
}
}