<?php
// src/EventSubscriber/VisitorSubscriber.php
namespace App\EventSubscriber;
use App\Entity\Visitor;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Doctrine\Persistence\ManagerRegistry;
class VisitorSubscriber implements EventSubscriberInterface
{
private EntityManagerInterface $entityManager;
private ManagerRegistry $doctrine;
public function __construct(ManagerRegistry $doctrine)
{
$this->doctrine = $doctrine;
$this->entityManager = $doctrine->getManager();
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => 'onKernelRequest',
KernelEvents::RESPONSE => 'onKernelResponse',
];
}
public function onKernelRequest(RequestEvent $event): void
{
$request = $event->getRequest();
// IP-Adresse des Besuchers
$ipAddress = $request->getClientIp();
$url = $request->getPathInfo();
// Liste der Pfade, die ignoriert werden sollen
$ignoredPaths = ['/vendors/', '/js/', '/css/', '/images/', '/fonts/', '/_wdt', '/_profiler'];
// Überprüfe, ob die URL zu einem ignorierten Pfad gehört
foreach ($ignoredPaths as $ignoredPath) {
if (strpos($url, $ignoredPath) !== false) {
return; // Überspringe das Tracking für diese URL
}
}
// Vermeide das Tracking für Admin-Seiten
if (strpos($url, '/admin') !== false) {
return;
}
// Überprüfen, ob der EntityManager geschlossen ist
if (!$this->entityManager->isOpen()) {
// Hole einen neuen EntityManager über den Doctrine-Manager-Service
$this->entityManager = $this->doctrine->resetManager();
}
// Suche nach einem bestehenden Besucher-Eintrag mit derselben IP-Adresse und URL
$visitor = $this->entityManager->getRepository(Visitor::class)->findOneBy([
'ipAddress' => $ipAddress,
'url' => $url,
]);
if (!$visitor) {
// Neues Besuch-Objekt erstellen, wenn kein Eintrag vorhanden ist
$visitor = new Visitor();
$visitor->setIpAddress($ipAddress);
$visitor->setUrl($url);
$visitor->setVisitedAt(new \DateTime());
$visitor->setVisitDuration(0); // Standardwert für die Besuchsdauer
$visitor->setClicks(1); // Initiale Klickzahl
$visitor->setUniqueClicks(1); // Initiale eindeutige Klickzahl
// Besuch in die Datenbank speichern
$this->entityManager->persist($visitor);
} else {
// Klick-Zähler aktualisieren
$visitor->setClicks($visitor->getClicks() + 1);
}
// Speichere die Visitor-Instanz in der Anfrage
$request->attributes->set('visitor', $visitor);
$this->entityManager->flush();
}
public function onKernelResponse(ResponseEvent $event): void
{
$request = $event->getRequest();
$visitor = $request->attributes->get('visitor');
if ($visitor instanceof Visitor) {
// Besuchsdauer berechnen und aktualisieren
$visitEnd = new \DateTime();
$visitDuration = $visitEnd->getTimestamp() - $visitor->getVisitedAt()->getTimestamp();
$visitor->setVisitDuration($visitDuration);
$visitor->setClicks($visitor->getClicks() + 1);
$this->entityManager->flush();
}
}
}