<?php declare(strict_types=1);
namespace WydnBackendStatistic\Storefront\Subscriber;
use Doctrine\DBAL\Connection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Storefront\Event\StorefrontRenderEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class StorefrontRenderSubscriber implements EventSubscriberInterface
{
/** @var EntityRepository $sessionRepository */
private EntityRepository $sessionRepository;
/** @var Connection $connection */
private Connection $connection;
/**
* @param EntityRepository $sessionRepository
* @param Connection $connection
*/
public function __construct(EntityRepository $sessionRepository, Connection $connection)
{
$this->sessionRepository = $sessionRepository;
$this->connection = $connection;
}
/**
* @return array[]
*/
public static function getSubscribedEvents(): array
{
return [
StorefrontRenderEvent::class => ['onRender', -1],
];
}
/**
* @param StorefrontRenderEvent $event
* @return void
*/
public function onRender(StorefrontRenderEvent $event): void
{
// remove old sessions to avoid performance issues
$this->removeOldSessions(65); // 65 minutes
$session = $event->getRequest()->getSession();
$server = $event->getRequest()->server;
// exclude bots
if(empty($server->get('HTTP_USER_AGENT')) || stristr($server->get('HTTP_USER_AGENT'), 'Bot') !== false) {
return;
}
// cloudflare ip
$ip = $server->get('HTTP_CF_CONNECTING_IP');
if (empty($ip)) {
// forwarded ip
$ip = $server->get('HTTP_X_FORWARDED_FOR');
$ip = explode(', ', $ip);
$ip = reset ($ip);
}
if (empty($ip)) {
// default
$ip = $server->get('REMOTE_ADDR');
}
$criteria = new Criteria();
$criteria->addFilter(new MultiFilter(
MultiFilter::CONNECTION_OR,
[
new EqualsFilter('ipHash', md5($ip)),
new EqualsFilter('sessionId', $session->getId())
]
));
$sessionRequest = $this->sessionRepository->search($criteria, $event->getContext())->first();
$this->sessionRepository->upsert([
[
'id' => ($sessionRequest != null ? $sessionRequest->getId() : Uuid::randomHex()),
'sessionId' => $session->getId(),
'ipHash' => md5($ip)
]
], $event->getContext());
}
/**
* @param int $maxTimeMinutes
* @return void
*/
private function removeOldSessions(int $maxTimeMinutes = 5) : void
{
try {
$this->connection->executeStatement('DELETE FROM wydn_session_request
WHERE (created_at < DATE_SUB(:nowDate, INTERVAL :maxTime MINUTE) AND updated_at IS NULL) OR
(updated_at < DATE_SUB(:nowDate, INTERVAL :maxTime MINUTE) and updated_at IS NOT NULL)', [
'maxTime' => $maxTimeMinutes,
'nowDate' => (new \DateTime())->format('Y-m-d H:i:s')
]);
} catch (\Exception $e) {
// do nothing
}
}
}