From a403628c07fd51deba9a34d182bf5893fbd738b5 Mon Sep 17 00:00:00 2001 From: "fefe.clochette" Date: Mon, 30 Mar 2026 12:21:47 +0200 Subject: [PATCH] geoloc --- modules/holidays/includes/api/geocode.php | 107 ++++++++++++---------- 1 file changed, 61 insertions(+), 46 deletions(-) diff --git a/modules/holidays/includes/api/geocode.php b/modules/holidays/includes/api/geocode.php index c0adf8b..e69b186 100644 --- a/modules/holidays/includes/api/geocode.php +++ b/modules/holidays/includes/api/geocode.php @@ -15,7 +15,6 @@ if ($q === '') { exit; } -// Borner la limite $limit = (int)($_GET['limit'] ?? 1); if ($limit < 1) $limit = 1; if ($limit > 10) $limit = 10; @@ -24,7 +23,6 @@ if ($limit > 10) $limit = 10; $qNorm = mb_strtolower($q); $qHash = hash('sha256', $qNorm); -// 3. Création automatique de la table cache try { $pdo->exec(" CREATE TABLE IF NOT EXISTS pf_geocode_cache ( @@ -38,28 +36,36 @@ try { "); } catch (Throwable $e) {} -// 4. Vérification du cache +// 3. Vérification du cache try { $st = $pdo->prepare("SELECT lat, lng, display_name FROM pf_geocode_cache WHERE q_hash = ?"); $st->execute([$qHash]); if ($row = $st->fetch(PDO::FETCH_ASSOC)) { - echo json_encode([ - 'lat' => (float)$row['lat'], - 'lng' => (float)$row['lng'], - 'display_name' => $row['display_name'], - 'cached' => true - ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + if ($limit === 1) { + echo json_encode([ + 'lat' => (float)$row['lat'], + 'lng' => (float)$row['lng'], + 'display_name' => $row['display_name'], + 'cached' => true + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + } else { + echo json_encode(['results' => [[ + 'lat' => (float)$row['lat'], + 'lng' => (float)$row['lng'], + 'display_name' => $row['display_name'], + 'cached' => true + ]]], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + } exit; } } catch (Throwable $e) {} -// 5. Appel Nominatim -$endpoint = 'https://nominatim.openstreetmap.org/search'; +// 4. NOUVELLE API : Appel à Photon (Komoot) - Beaucoup plus tolérant pour les adresses ! +$endpoint = 'https://photon.komoot.io/api/'; $params = http_build_query([ - 'format' => 'jsonv2', - 'addressdetails' => 1, - 'limit' => $limit, - 'q' => $q, + 'q' => $q, + 'limit' => $limit, + 'lang' => 'fr' // On force les résultats en français ], '', '&', PHP_QUERY_RFC3986); $url = $endpoint . '?' . $params; @@ -69,65 +75,74 @@ curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_CONNECTTIMEOUT => 5, CURLOPT_TIMEOUT => 10, - CURLOPT_HTTPHEADER => [ - 'User-Agent: PachaFamily-Holidays/1.0 (+contact: ferlan.alexandre@gmail.com)' - ], + CURLOPT_USERAGENT => 'PachaFamily-Holidays/1.0', + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false ]); $body = curl_exec($ch); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); -$err = curl_error($ch); curl_close($ch); if ($body === false || $http !== 200) { http_response_code(502); - echo json_encode([ - 'error' => 'geocode_failed', - 'details' => $err ?: ('HTTP ' . $http) - ]); + echo json_encode(['error' => 'geocode_failed']); exit; } $data = json_decode($body, true); -if (!is_array($data) || empty($data)) { +if (!isset($data['features']) || empty($data['features'])) { http_response_code(404); echo json_encode(['error' => 'not_found']); exit; } -// 6. Mise en cache -if (isset($data[0])) { - $r = $data[0]; - $lat = round((float)$r['lat'], 6); - $lng = round((float)$r['lon'], 6); - $display = $r['display_name'] ?? ''; +// 5. Formatage des résultats (Photon renvoie les données différemment de Nominatim) +$results = []; +foreach ($data['features'] as $feature) { + $prop = $feature['properties']; + $coords = $feature['geometry']['coordinates']; // [lng, lat] + + // Construction propre du nom (Nom du lieu + Rue + Ville + Pays) + $nameParts = []; + if (!empty($prop['name'])) $nameParts[] = $prop['name']; + + if (!empty($prop['housenumber']) && !empty($prop['street'])) { + $nameParts[] = $prop['housenumber'] . ' ' . $prop['street']; + } elseif (!empty($prop['street'])) { + $nameParts[] = $prop['street']; + } + + if (!empty($prop['city'])) $nameParts[] = $prop['city']; + elseif (!empty($prop['town'])) $nameParts[] = $prop['town']; + elseif (!empty($prop['village'])) $nameParts[] = $prop['village']; + + if (!empty($prop['country'])) $nameParts[] = $prop['country']; + + $displayName = implode(', ', array_unique($nameParts)); + + $results[] = [ + 'lat' => round((float)$coords[1], 6), + 'lng' => round((float)$coords[0], 6), + 'display_name' => $displayName + ]; +} +// 6. Mise en cache du premier résultat +if (isset($results[0])) { try { $st = $pdo->prepare(" INSERT INTO pf_geocode_cache (q_hash, q, lat, lng, display_name, updated_at) VALUES (?, ?, ?, ?, ?, NOW()) ON DUPLICATE KEY UPDATE lat=VALUES(lat), lng=VALUES(lng), display_name=VALUES(display_name), updated_at=NOW() "); - $st->execute([$qHash, $q, $lat, $lng, $display]); + $st->execute([$qHash, $q, $results[0]['lat'], $results[0]['lng'], $results[0]['display_name']]); } catch (Throwable $e) {} } -// 7. Retour +// 7. Retour JSON pour ton Javascript if ($limit === 1) { - $r = $data[0]; - echo json_encode([ - 'lat' => round((float)$r['lat'], 6), - 'lng' => round((float)$r['lon'], 6), - 'display_name' => $r['display_name'] ?? '' - ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + echo json_encode($results[0], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } else { - $results = array_map(function ($r) { - return [ - 'lat' => round((float)$r['lat'], 6), - 'lng' => round((float)$r['lon'], 6), - 'display_name' => (string)($r['display_name'] ?? ''), - ]; - }, $data); - echo json_encode(['results' => $results], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } \ No newline at end of file