- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
136 lines
3.8 KiB
PHP
136 lines
3.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Infrastructure\GeoIp;
|
|
|
|
use App\Framework\Core\ValueObjects\CountryCode;
|
|
use App\Framework\Database\PdoConnection;
|
|
use App\Framework\Http\IpAddress;
|
|
use PDO;
|
|
|
|
final class GeoIp
|
|
{
|
|
private readonly PDO $database;
|
|
|
|
private readonly IpRangeService $ipRangeService;
|
|
|
|
private readonly CountryDataService $countryDataService;
|
|
|
|
public function __construct(?string $databasePath = null)
|
|
{
|
|
$databasePath = $databasePath ?? __DIR__ . '/data/ip_country.sqlite';
|
|
$this->database = $this->initializeDatabase($databasePath);
|
|
$connection = new PdoConnection($this->database);
|
|
$this->ipRangeService = new IpRangeService($connection);
|
|
$this->countryDataService = new CountryDataService($connection);
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use DatabaseSetup::setupCompleteDatabase() instead
|
|
*/
|
|
public function loadDatabase(): void
|
|
{
|
|
$setup = new DatabaseSetup(__DIR__ . '/data/ip_country.sqlite');
|
|
$setup->setupIpRangesOnly();
|
|
}
|
|
|
|
public function getCountryForString(string $ip): ?string
|
|
{
|
|
return $this->ipRangeService->getCountryCodeForIp($ip);
|
|
}
|
|
|
|
public function getCountryForIp(IpAddress $ipAddress): ?string
|
|
{
|
|
if ($ipAddress->isPrivate()) {
|
|
return null;
|
|
}
|
|
|
|
return $this->getCountryForString($ipAddress->value);
|
|
}
|
|
|
|
public function getCountryCode(IpAddress $ipAddress): CountryCode
|
|
{
|
|
if ($ipAddress->isPrivate()) {
|
|
// Return a default country code for private IPs (e.g., local development)
|
|
return CountryCode::fromString('XX'); // XX = Unknown/Private
|
|
}
|
|
|
|
$countryCodeString = $this->getCountryForString($ipAddress->value);
|
|
|
|
if ($countryCodeString === null) {
|
|
return CountryCode::fromString('XX'); // Unknown
|
|
}
|
|
|
|
return CountryCode::fromString($countryCodeString);
|
|
}
|
|
|
|
public function getCountryInfo(string $ip): CountryInfo
|
|
{
|
|
$countryCode = $this->getCountryForString($ip);
|
|
|
|
if (! $countryCode) {
|
|
return new CountryInfo($ip, null);
|
|
}
|
|
|
|
$country = $this->countryDataService->getCountryByCode($countryCode);
|
|
|
|
return new CountryInfo($ip, $countryCode, $country);
|
|
}
|
|
|
|
public function getCountryInfoForIp(IpAddress $ipAddress): CountryInfo
|
|
{
|
|
if ($ipAddress->isPrivate()) {
|
|
return new CountryInfo($ipAddress->value, null);
|
|
}
|
|
|
|
return $this->getCountryInfo($ipAddress->value);
|
|
}
|
|
|
|
public function getCountryNameGerman(string $ip): ?string
|
|
{
|
|
return $this->getCountryInfo($ip)->getGermanName();
|
|
}
|
|
|
|
public function getCountryNameEnglish(string $ip): ?string
|
|
{
|
|
return $this->getCountryInfo($ip)->getEnglishName();
|
|
}
|
|
|
|
public function getCountryNameNative(string $ip): ?string
|
|
{
|
|
return $this->getCountryInfo($ip)->getNativeName();
|
|
}
|
|
|
|
private function initializeDatabase(string $file): PDO
|
|
{
|
|
$directory = dirname($file);
|
|
if (! is_dir($directory)) {
|
|
mkdir($directory, 0755, true);
|
|
}
|
|
|
|
$db = new PDO('sqlite:' . $file);
|
|
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
|
|
// IP-Ranges Tabelle
|
|
$db->exec('CREATE TABLE IF NOT EXISTS ip_ranges (
|
|
id INTEGER PRIMARY KEY,
|
|
ip_start INTEGER,
|
|
ip_end INTEGER,
|
|
country TEXT
|
|
)');
|
|
$db->exec('CREATE INDEX IF NOT EXISTS idx_ip_range ON ip_ranges (ip_start, ip_end)');
|
|
|
|
// Länder-Tabelle für ISO-Daten
|
|
$db->exec('CREATE TABLE IF NOT EXISTS countries (
|
|
code TEXT PRIMARY KEY,
|
|
name_en TEXT,
|
|
name_de TEXT,
|
|
name_native TEXT,
|
|
updated_at TEXT
|
|
)');
|
|
|
|
return $db;
|
|
}
|
|
}
|