<?php
declare(strict_types=1);
namespace BitBag\OpenMarketplace\Component\Core\Shop\Controller\Map;
use GeoIp2\Database\Reader;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Twig\Environment;
/**
* Renders the Hyfindr map page and resolves an initial map center from the
* visitor's IP (GeoLite2). Falls back to null (frontend default) for local /
* private IPs or when the lookup fails. Never throws on geoip errors.
*/
final class MapIndexAction
{
private const TEMPLATE = 'Context/HyfindrMap/index.html.twig';
public function __construct(
private Environment $twig,
private RequestStack $requestStack,
private Reader $geoIpReader,
) {
}
public function __invoke(): Response
{
return new Response($this->twig->render(self::TEMPLATE, [
'initialCenter' => $this->resolveInitialCenter(),
]));
}
/**
* @return array{0: float, 1: float}|null [longitude, latitude]
*/
private function resolveInitialCenter(): ?array
{
$request = $this->requestStack->getCurrentRequest();
if (null === $request) {
return null;
}
$ip = $request->getClientIp();
if (null === $ip || !$this->isPublicIp($ip)) {
return null;
}
try {
$record = $this->geoIpReader->city($ip);
$latitude = $record->location->latitude;
$longitude = $record->location->longitude;
} catch (\Throwable) {
return null;
}
if (null === $latitude || null === $longitude) {
return null;
}
return [(float) $longitude, (float) $latitude];
}
private function isPublicIp(string $ip): bool
{
return false !== filter_var(
$ip,
FILTER_VALIDATE_IP,
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE,
);
}
}