- 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
103 lines
3.1 KiB
PHP
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')
|
|
);
|
|
}
|
|
}
|