Files
kupshop/bundles/KupShop/I18nBundle/Util/IPGeoLocator.php
2025-08-02 16:30:27 +02:00

166 lines
4.7 KiB
PHP

<?php
namespace KupShop\I18nBundle\Util;
use KupShop\KupShopBundle\Util\Compat\SymfonyBridge;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class IPGeoLocator
{
// caching server for geoPlugin server
protected $host;
// the default base currency
protected $currency = 'CZK';
protected $cache;
protected $proxyCache;
/**
* @var RequestStack
*/
protected $requestStack;
protected $logger;
public function __construct(RequestStack $requestStack, LoggerInterface $logger)
{
$this->requestStack = $requestStack;
$this->logger = $logger;
$urlSuffix = '/geoip?ip={IP}&base_currency={CURRENCY}&id_shop={ID_SHOP}';
$this->host = (isRunningOnCluster() ? 'geoip.services' : 'http://geoip.wpj.cz').$urlSuffix;
}
/**
* Gets geographical info from users request. When proxy is enabled, it tries to take the info from the headers that the proxy set.
*
* @param $fullInfo bool when false, guaranteed IPGeoLocatorResult attributes are only ip, countryCode and currencyCode. When more information is needed (e.g. latitude/longitude), fullInfo parameter has to be true
*
* @return IPGeoLocatorResult
*/
public function getInfo(bool $fullInfo = false)
{
$result = null;
if (findModule(\Modules::PROXY_CACHE) && !$fullInfo) {
$result = $this->getInfoFromProxy();
}
if (!$result) {
$result = $this->getGeoLocatorInfo();
}
return $result;
}
protected function getGeoLocatorInfo()
{
if ($this->cache) {
return $this->cache;
}
$ip = $this->getClientIp();
$data = $this->locate($ip);
return $this->cache = $this->createResult($data);
}
protected function getInfoFromProxy()
{
if ($this->proxyCache) {
return $this->proxyCache;
}
$countryCode = $this->getRequest()->headers->get('Cdn-Requestcountrycode');
if (!$countryCode) {
return false;
}
$currencyCode = (new \NumberFormatter('en_'.$countryCode, \NumberFormatter::CURRENCY))->getTextAttribute(\NumberFormatter::CURRENCY_CODE);
if (!$currencyCode || $currencyCode == 'XXX') {
return false;
}
$data = [
'geoplugin_countryCode' => $countryCode,
'geoplugin_currencyCode' => $currencyCode,
'ip' => $this->getClientIp(),
];
return $this->proxyCache = $this->createResult($data);
}
protected function getClientIp()
{
return $this->getRequest()->getClientIp();
}
protected function getRequest()
{
$request = $this->requestStack->getMainRequest();
if (is_null($request)) {
$request = SymfonyBridge::getCurrentRequest();
}
return $request;
}
protected function fetch($host)
{
// use cURL to fetch data
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $host);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'geoPlugin PHP Class v1.0');
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1000);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
protected function locate($ip)
{
$host = str_replace('{IP}', $ip, $this->host);
$host = str_replace('{CURRENCY}', $this->currency, $host);
$host = str_replace('{ID_SHOP}', getShopUniqueName(), $host);
$response = $this->fetch($host);
return json_decode($response, true);
}
/**
* @param $data array
*
* @return IPGeoLocatorResult
*/
protected function createResult($data)
{
$result = new IPGeoLocatorResult();
// set the geoPlugin vars
$result->ip = $data['ip'] ?? null;
$result->city = $data['geoplugin_city'] ?? null;
$result->region = $data['geoplugin_region'] ?? null;
$result->areaCode = $data['geoplugin_areaCode'] ?? null;
$result->dmaCode = $data['geoplugin_dmaCode'] ?? null;
$result->countryCode = $data['geoplugin_countryCode'] ?? null;
$result->countryName = $data['geoplugin_countryName'] ?? null;
$result->continentCode = $data['geoplugin_continentCode'] ?? null;
$result->latitude = $data['geoplugin_latitude'] ?? null;
$result->longitude = $data['geoplugin_longitude'] ?? null;
$result->currencyCode = $data['geoplugin_currencyCode'] ?? null;
$result->currencySymbol = $data['geoplugin_currencySymbol'] ?? null;
$result->currencyConverter = $data['geoplugin_currencyConverter'] ?? null;
return $result;
}
}