misuzu/src/GeoIP/GeoIPHelper.php

77 lines
2.5 KiB
PHP

<?php
namespace Misuzu\GeoIP;
use InvalidArgumentException;
use RuntimeException;
use Index\Net\IPAddress;
use GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException;
use GeoIp2\Model\Asn;
use GeoIp2\Model\City;
use GeoIp2\Model\Country;
use Misuzu\Config\IConfig;
class GeoIPHelper {
public const ASN = 'asn';
public const CITY = 'city';
public const COUNTRY = 'country';
private IConfig $config;
private array $readers = [];
public function __construct(IConfig $config) {
$this->config = $config;
}
public function hasDbPath(string $type): bool {
return array_key_exists($type, $this->readers)
|| $this->config->hasValue('db.' . $type);
}
public function getDbPath(string $type): string {
$type = 'db.' . $type;
if(!$this->config->hasValue($type))
throw new RuntimeException('Not database path has been configured for $type.');
return $this->config->getValue($type, IConfig::T_STR);
}
public function getReader(string $type): Reader {
if(!array_key_exists($type, $this->readers))
return $this->readers[$type] = new Reader($this->getDbPath($type));
return $this->readers[$type];
}
public function getASN(IPAddress|string $ipAddress): Asn {
if($ipAddress instanceof IPAddress)
$ipAddress = $ipAddress->getCleanAddress();
if($this->hasDbPath(self::ASN))
return $this->getReader(self::ASN)->asn($ipAddress);
throw new RuntimeException('There was no database available that could satisfy this request.');
}
public function getCityOrCountry(IPAddress|string $ipAddress): City|Country {
if($ipAddress instanceof IPAddress)
$ipAddress = $ipAddress->getCleanAddress();
if($this->hasDbPath(self::CITY))
return $this->getReader(self::CITY)->city($ipAddress);
if($this->hasDbPath(self::COUNTRY))
return $this->getReader(self::COUNTRY)->country($ipAddress);
throw new RuntimeException('There was no database available that could satisfy this request.');
}
public function getIsoCountryCode(IPAddress|string $ipAddress, string $fallback = 'XX'): string {
try {
return $this->getCityOrCountry($ipAddress)->country->isoCode ?? $fallback;
} catch(AddressNotFoundException $ex) {
return $fallback;
} catch(RuntimeException $ex) {
return $fallback;
}
}
}