<?php
namespace App\Service\Stats;
use App\Entity\Stats\Visitor;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Security;
class VisitorLogger
{
private $entityManager;
private $requestStack;
private $security;
public function __construct(EntityManagerInterface $entityManager, RequestStack $requestStack, Security $security)
{
$this->entityManager = $entityManager;
$this->requestStack = $requestStack;
$this->security = $security;
}
public function logVisit()
{
$request = $this->requestStack->getCurrentRequest();
if (!$request) {
return;
}
$route = $request->attributes->get('_route');
// Skip logging for certain route prefixes
if ($this->shouldSkipLogging($route) || $this->isJsonRequest($request)) {
return;
}
$ip = $request->getClientIp();
$url = $request->getUri();
$userAgent = $request->headers->get('User-Agent');
$referrer = $request->headers->get('referer');
$country = $this->getCountry($ip);
$city = $this->getCity($ip);
$visitor = $this->entityManager->getRepository(Visitor::class)->findOneBy([
'ip' => $ip,
'route' => $route,
]);
$currentTimestamp = new \DateTime();
if ($visitor) {
// Check if the time difference from the last visit is greater than 3 seconds
$lastVisitedAt = $visitor->getLastVisitedAt();
$timeDiff = $currentTimestamp->getTimestamp() - $lastVisitedAt->getTimestamp();
if ($timeDiff >= 3) {
$visitor->setLastVisitedAt($currentTimestamp);
$visitor->setVisits($visitor->getVisits() + 1);
$this->entityManager->flush();
}
} else {
$visitor = new Visitor();
$visitor->setLastVisitedAt($currentTimestamp);
$visitor->setVisits(1);
$visitor->setRoute($route);
$visitor->setUrl($url);
$visitor->setReferrer($referrer);
$visitor->setIp($ip);
$visitor->setOs($this->getOS($userAgent));
$visitor->setBrowser($this->getBrowser($userAgent));
$visitor->setCountry($country);
$visitor->setCity($city);
$this->entityManager->persist($visitor);
$this->entityManager->flush();
}
}
private function shouldSkipLogging(string $route): bool
{
$excludedPrefixes = [
'api_', // Example prefix for API routes
'login', // Example prefix for API routes
'_', // Example prefix for internal routes like _wdt, _profiler, etc.
'admin', // Example prefix for admin routes
];
foreach ($excludedPrefixes as $prefix) {
if (strpos($route, $prefix) === 0) {
return true;
}
}
return false;
}
private function isJsonRequest($request): bool
{
return str_contains($request->headers->get('Accept'), 'application/json');
}
private function getOS(string $userAgent): string
{
if (preg_match('/Linux/', $userAgent)) {
return 'Linux';
} elseif (preg_match('/Mac/i', $userAgent)) {
return 'Mac';
} elseif (preg_match('/Windows/', $userAgent)) {
return 'Windows';
} else {
return 'Unknown OS';
}
}
private function getBrowser(string $userAgent): string
{
if (preg_match('/Firefox/', $userAgent)) {
return 'Firefox';
} elseif (preg_match('/Chrome/', $userAgent)) {
return 'Chrome';
} elseif (preg_match('/Safari/', $userAgent)) {
return 'Safari';
} elseif (preg_match('/MSIE/', $userAgent)) {
return 'Internet Explorer';
} else {
return 'Unknown Browser';
}
}
private function getCountry(string $ip): string
{
return 'Unknown Country';
}
private function getCity(string $ip): string
{
return 'Unknown City';
}
}