78 lines
2.5 KiB
PHP
78 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;
|
||
|
use Misuzu\Config\CfgType;
|
||
|
|
||
|
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, CfgType::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;
|
||
|
}
|
||
|
}
|
||
|
}
|