This commit is contained in:
@@ -192,6 +192,40 @@ final class AccountPages
|
||||
$languagesEnc = self::encryptOptionalProfileField($crypto, trim((string)$languages));
|
||||
$aboutEnc = self::encryptOptionalProfileField($crypto, trim((string)$_POST['about']));
|
||||
$locationPreference = (string)($_POST['location_tracking_preference'] ?? 'prompt');
|
||||
$street = trim((string)($_POST['street'] ?? ''));
|
||||
$zip = trim((string)($_POST['zip'] ?? ''));
|
||||
$city = trim((string)($_POST['city'] ?? ''));
|
||||
$region = trim((string)($_POST['region'] ?? ''));
|
||||
$lat = isset($_POST['lat']) && $_POST['lat'] !== '' ? (float)$_POST['lat'] : null;
|
||||
$lng = isset($_POST['lng']) && $_POST['lng'] !== '' ? (float)$_POST['lng'] : null;
|
||||
|
||||
$hasAddress = $street !== '' || $zip !== '' || $city !== '' || $region !== '';
|
||||
if ($hasAddress) {
|
||||
$resolvedAddress = null;
|
||||
if ($lat !== null && $lng !== null) {
|
||||
$resolvedAddress = self::reverseGeocodeAddress($lat, $lng);
|
||||
}
|
||||
if ($resolvedAddress === null) {
|
||||
$searchResults = self::geocodeAddressCandidates($street, $zip, $city, $region, 5);
|
||||
if (!$searchResults) {
|
||||
throw new \RuntimeException('Die Profiladresse konnte nicht validiert werden. Bitte waehle eine Adresse aus der Suche oder ueber den Browser-Standort.');
|
||||
}
|
||||
$resolvedAddress = $searchResults[0];
|
||||
}
|
||||
|
||||
$street = $resolvedAddress['street'] !== '' ? $resolvedAddress['street'] : $street;
|
||||
$zip = $resolvedAddress['zip'] !== '' ? $resolvedAddress['zip'] : $zip;
|
||||
$city = $resolvedAddress['city'] !== '' ? $resolvedAddress['city'] : $city;
|
||||
$region = $resolvedAddress['region'] !== '' ? $resolvedAddress['region'] : $region;
|
||||
$lat = $resolvedAddress['lat'];
|
||||
$lng = $resolvedAddress['lng'];
|
||||
} else {
|
||||
$lat = null;
|
||||
$lng = null;
|
||||
$region = '';
|
||||
}
|
||||
|
||||
$streetEnc = self::encryptOptionalProfileField($crypto, $street);
|
||||
if ($profileSettings) {
|
||||
$profileSettings->ensureSchema();
|
||||
}
|
||||
@@ -201,11 +235,11 @@ final class AccountPages
|
||||
'fname' => $firstNameEnc,
|
||||
'lname' => $lastNameEnc,
|
||||
'street' => $streetEnc,
|
||||
'zip' => trim((string)$_POST['zip']),
|
||||
'city' => trim((string)$_POST['city']),
|
||||
'region' => trim((string)($_POST['region'] ?? '')),
|
||||
'lat' => isset($_POST['lat']) && $_POST['lat'] !== '' ? (float)$_POST['lat'] : null,
|
||||
'lng' => isset($_POST['lng']) && $_POST['lng'] !== '' ? (float)$_POST['lng'] : null,
|
||||
'zip' => $zip,
|
||||
'city' => $city,
|
||||
'region' => $region,
|
||||
'lat' => $lat,
|
||||
'lng' => $lng,
|
||||
'prof' => $professionEnc,
|
||||
'langs' => $languagesEnc,
|
||||
'about' => $aboutEnc,
|
||||
@@ -629,6 +663,17 @@ final class AccountPages
|
||||
}
|
||||
|
||||
private static function geocodeAddress(?string $street, ?string $zip, ?string $city, ?string $region): array
|
||||
{
|
||||
$candidates = self::geocodeAddressCandidates($street, $zip, $city, $region, 1);
|
||||
if (!$candidates) {
|
||||
return [null, null, null];
|
||||
}
|
||||
|
||||
$best = $candidates[0];
|
||||
return [$best['lat'], $best['lng'], $best['region'] !== '' ? $best['region'] : null];
|
||||
}
|
||||
|
||||
private static function geocodeAddressCandidates(?string $street, ?string $zip, ?string $city, ?string $region, int $limit = 5): array
|
||||
{
|
||||
$parts = array_filter([
|
||||
$street ?: null,
|
||||
@@ -643,10 +688,75 @@ final class AccountPages
|
||||
$query = implode(', ', $parts);
|
||||
$url = 'https://nominatim.openstreetmap.org/search?' . http_build_query([
|
||||
'format' => 'jsonv2',
|
||||
'limit' => 1,
|
||||
'limit' => max(1, min(10, $limit)),
|
||||
'addressdetails' => 1,
|
||||
'q' => $query,
|
||||
]);
|
||||
|
||||
$resp = self::fetchGeoJson($url);
|
||||
if ($resp === null) {
|
||||
return [];
|
||||
}
|
||||
$json = json_decode($resp, true);
|
||||
if (!is_array($json)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$results = [];
|
||||
foreach ($json as $item) {
|
||||
if (!is_array($item) || empty($item['lat']) || empty($item['lon'])) {
|
||||
continue;
|
||||
}
|
||||
$results[] = self::normalizeGeoAddressResult($item);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
private static function reverseGeocodeAddress(float $lat, float $lng): ?array
|
||||
{
|
||||
$url = 'https://nominatim.openstreetmap.org/reverse?' . http_build_query([
|
||||
'format' => 'jsonv2',
|
||||
'addressdetails' => 1,
|
||||
'lat' => $lat,
|
||||
'lon' => $lng,
|
||||
]);
|
||||
|
||||
$resp = self::fetchGeoJson($url);
|
||||
if ($resp === null) {
|
||||
return null;
|
||||
}
|
||||
$json = json_decode($resp, true);
|
||||
if (!is_array($json) || empty($json['lat']) || empty($json['lon'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::normalizeGeoAddressResult($json);
|
||||
}
|
||||
|
||||
private static function normalizeGeoAddressResult(array $item): array
|
||||
{
|
||||
$addr = is_array($item['address'] ?? null) ? $item['address'] : [];
|
||||
$street = trim(implode(' ', array_filter([
|
||||
(string)($addr['road'] ?? ''),
|
||||
(string)($addr['house_number'] ?? ''),
|
||||
])));
|
||||
$city = (string)($addr['city'] ?? $addr['town'] ?? $addr['village'] ?? '');
|
||||
$region = (string)($addr['city_district'] ?? $addr['suburb'] ?? $addr['state'] ?? $addr['county'] ?? $addr['region'] ?? $addr['state_district'] ?? '');
|
||||
|
||||
return [
|
||||
'label' => trim((string)($item['display_name'] ?? '')),
|
||||
'street' => $street,
|
||||
'zip' => (string)($addr['postcode'] ?? ''),
|
||||
'city' => $city,
|
||||
'region' => $region,
|
||||
'lat' => round((float)$item['lat'], 7),
|
||||
'lng' => round((float)$item['lon'], 7),
|
||||
];
|
||||
}
|
||||
|
||||
private static function fetchGeoJson(string $url): ?string
|
||||
{
|
||||
$ctx = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'GET',
|
||||
@@ -656,15 +766,6 @@ final class AccountPages
|
||||
]);
|
||||
|
||||
$resp = @file_get_contents($url, false, $ctx);
|
||||
if ($resp === false) {
|
||||
return [null, null, null];
|
||||
}
|
||||
$json = json_decode($resp, true);
|
||||
if (!is_array($json) || empty($json[0]['lat']) || empty($json[0]['lon'])) {
|
||||
return [null, null, null];
|
||||
}
|
||||
$addr = $json[0]['address'] ?? [];
|
||||
$regionGuess = $addr['city_district'] ?? $addr['suburb'] ?? $addr['state'] ?? $addr['county'] ?? $addr['region'] ?? $addr['state_district'] ?? null;
|
||||
return [round((float)$json[0]['lat'], 7), round((float)$json[0]['lon'], 7), $regionGuess];
|
||||
return $resp === false ? null : $resp;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user