<?php
namespace App\Manager;
use App\Entity\Seed;
use App\Entity\Tracker;
use App\Enum\Product;
use App\Enum\Home;
use App\Enum\Source;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;
use Psr\Log\LoggerInterface;
class SeedManager
{
private Request $request;
private SessionInterface $session;
private ManagerRegistry $managerRegistry;
private ObjectManager $doctrineObjectManager;
private Seed $seed;
private LoggerInterface $logger;
public function __construct(RequestStack $requestStack, ManagerRegistry $managerRegistry, LoggerInterface $logger)
{
if (!$request = $requestStack->getCurrentRequest()) {
throw new \Exception('++++>No request defined');
}
$this->request = $request;
$this->session = $request->getSession();
$this->managerRegistry = $managerRegistry;
$this->doctrineObjectManager = $managerRegistry->getManager();
$this->seed = new Seed(Product::none, Home::undifined, Source::none, '', '', '', '');
$this->logger = $logger;
}
public function save(Product $eProduct, Home $eHome, string $sTemplate, bool $bOriginToken = false): Seed
{
$bRefreshSeedInSession = false;
/** @var int|null $iSeedId */
if (! $iSeedId = (int)$this->session->get('iSeedId')) {
$this->setCurrentSeedDetails($eProduct, $eHome, $bOriginToken);
$this->doctrineObjectManager->persist($this->seed);
} else {
$seed = $this->doctrineObjectManager->getRepository(Seed::class)->find($iSeedId);
if (! $seed) {//marginal case when iSeedId in session but not in db
$this->logger->error('---->SeedManager : not found iSeedId : ' . $iSeedId);
$this->setCurrentSeedDetails($eProduct, $eHome, $bOriginToken);
$this->doctrineObjectManager->persist($this->seed);
$bRefreshSeedInSession = true;
} else {
$this->seed = $seed;
}
}
$tracker = new Tracker($this->seed, $sTemplate, (string)$this->request->headers->get('referer'));
$this->doctrineObjectManager->persist($tracker);
$this->doctrineObjectManager->flush();
//PHP Session
if (! $iSeedId) {
$this->session->set('iSeedId', $this->seed->getId());
} elseif ($bRefreshSeedInSession) {
$this->session->set('iSeedId', $this->seed->getId());
}
$this->session->set('eProduct', $eProduct);
return $this->seed;
}
public function getManagerRegistry(): ManagerRegistry
{
return $this->managerRegistry;
}
private function getOriginToken(): string
{
$aTokenSource = ['gclid', 'fbclid', 'msclkid'];
//on [] current return false
return (string)current(array_intersect_key($this->request->query->all(), array_flip($aTokenSource)));
}
private function setCurrentSeedDetails(Product $eProduct, Home $eHome, bool $bOriginToken): void
{
$this->seed->setEProduct($eProduct);
$this->seed->setEHome($eHome);
$this->seed->setSPhpSession($this->session->getId());
$this->seed->setSIp($this->request->headers->get('x-real-ip') ?? $this->request->getClientIp() ?? 'unknown');
$this->seed->setSUserAgent((string)$this->request->headers->get('User-Agent'));
$this->seed->setSHeader(serialize($this->request->headers));
/**
* @psalm-suppress InternalMethod
*/
if ($this->request->get('sSource') !== null) {
$sSourceValue = (string) $this->request->get('sSource');
if (!Source::tryFrom($sSourceValue)) {
$this->logger->warning('Invalid sSource value: ' . $sSourceValue . '. Setting to "unknown".');
$this->seed->setESource(Source::unknown);
} else {
$this->seed->setESource(Source::from($sSourceValue));
}
}
/**
* @psalm-suppress InternalMethod
*/
if ($this->request->get('sOrigin') !== null) {
$this->seed->setSOrigin((string) $this->request->get('sOrigin'));
}
/**
* @psalm-suppress InternalMethod
*/
if ($this->request->get('sModel') !== null) {
$this->seed->setSModel((string) $this->request->get('sModel'));
}
/**
* @psalm-suppress InternalMethod
*/
if ($this->request->get('sVersion') !== null) {
$this->seed->setSVersion((string) $this->request->get('sVersion'));
}
/**
* @psalm-suppress InternalMethod
*/
if ($this->request->get('sObs') !== null) {
$this->seed->setSObs((string) $this->request->get('sObs'));
}
if ($bOriginToken && $sToken = $this->getOriginToken()) {
$this->seed->setSOriginToken($sToken);
}
}
}