Files
michaelschiemer/src/Infrastructure/GeoIp/CountryDataService.php
Michael Schiemer 5050c7d73a docs: consolidate documentation into organized structure
- Move 12 markdown files from root to docs/ subdirectories
- Organize documentation by category:
  • docs/troubleshooting/ (1 file)  - Technical troubleshooting guides
  • docs/deployment/      (4 files) - Deployment and security documentation
  • docs/guides/          (3 files) - Feature-specific guides
  • docs/planning/        (4 files) - Planning and improvement proposals

Root directory cleanup:
- Reduced from 16 to 4 markdown files in root
- Only essential project files remain:
  • CLAUDE.md (AI instructions)
  • README.md (Main project readme)
  • CLEANUP_PLAN.md (Current cleanup plan)
  • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements)

This improves:
 Documentation discoverability
 Logical organization by purpose
 Clean root directory
 Better maintainability
2025-10-05 11:05:04 +02:00

103 lines
3.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Infrastructure\GeoIp;
use PDO;
use RuntimeException;
use App\Framework\Database\ConnectionInterface;
use App\Framework\Database\ValueObjects\SqlQuery;
final class CountryDataService
{
private const string RESTCOUNTRIES_API_URL = 'https://restcountries.com/v3.1/all?fields=cca2,name,translations';
public function __construct(
private readonly ConnectionInterface $connection
) {
}
public function loadCountryData(): int
{
echo "Lade Länderdaten von RestCountries API...\n";
$jsonData = file_get_contents(self::RESTCOUNTRIES_API_URL);
if (! $jsonData) {
throw new RuntimeException('Konnte Länderdaten nicht herunterladen');
}
$countries = json_decode($jsonData, true);
if (! $countries) {
throw new RuntimeException('Ungültige JSON-Daten erhalten');
}
$this->connection->beginTransaction();
$this->connection->execute(SqlQuery::create('DELETE FROM countries'));
$insertSql = 'INSERT INTO countries (code, name_en, name_de, name_native, updated_at) VALUES (?, ?, ?, ?, ?)';
$processed = 0;
foreach ($countries as $countryData) {
$country = $this->parseCountryData($countryData);
if ($country) {
$this->connection->execute(SqlQuery::create($insertSql, [
$country->code,
$country->nameEn,
$country->nameDe,
$country->nameNative,
$country->updatedAt,
]));
$processed++;
}
}
$this->connection->commit();
echo "Länderdatenbank aktualisiert: {$processed} Länder geladen\n";
return $processed;
}
public function getCountryByCode(string $code): ?Country
{
$sql = 'SELECT code, name_en, name_de, name_native, updated_at FROM countries WHERE code = ?';
$result = $this->connection->queryOne(SqlQuery::create($sql, [$code]));
if (! $result) {
return null;
}
return new Country(
code: $result['code'],
nameEn: $result['name_en'],
nameDe: $result['name_de'],
nameNative: $result['name_native'],
updatedAt: $result['updated_at']
);
}
private function parseCountryData(array $countryData): ?Country
{
$code = $countryData['cca2'] ?? null;
$nameEn = $countryData['name']['common'] ?? null;
if (! $code || ! $nameEn) {
return null;
}
$nameDe = $countryData['translations']['deu']['common'] ?? $nameEn;
$nativeNames = $countryData['name']['nativeName'] ?? [];
$nameNative = ! empty($nativeNames)
? $nativeNames[array_key_first($nativeNames)]['common'] ?? $nameEn
: $nameEn;
return new Country(
code: $code,
nameEn: $nameEn,
nameDe: $nameDe,
nameNative: $nameNative,
updatedAt: date('Y-m-d H:i:s')
);
}
}