| |
| <?php
|
| <?php
|
|
|
|
|
|
|
|
|
|
|
| define('GMT_CERGY_LAT', 49.0361);
|
| define('GMT_CERGY_LON', 2.0761);
|
|
|
| add_action('rest_api_init', function () {
|
| register_rest_route('gmt/v1', '/distance', [
|
| 'methods' => 'GET',
|
| 'callback' => 'gmt_get_distance_from_cergy',
|
| 'permission_callback' => '__return_true',
|
| 'args' => [
|
| 'city' => ['required' => true],
|
| 'lat' => ['required' => false],
|
| 'lon' => ['required' => false],
|
| ],
|
| ]);
|
| });
|
|
|
| function gmt_slugify_city($value) {
|
| return sanitize_title(remove_accents(strtolower(trim($value))));
|
| }
|
|
|
| function gmt_nominatim_search($query) {
|
| $url = 'https://nominatim.openstreetmap.org/search?' . http_build_query([
|
| 'q' => $query,
|
| 'format' => 'json',
|
| 'countrycodes' => 'fr',
|
| 'limit' => 5,
|
| 'addressdetails' => 1,
|
| ]);
|
| $response = wp_remote_get($url, [
|
| 'headers' => ['User-Agent' => 'GreenMultitechDistanceTool/1.0 ([email protected])'],
|
| 'timeout' => 8,
|
| ]);
|
| if (is_wp_error($response)) return null;
|
| $body = json_decode(wp_remote_retrieve_body($response), true);
|
| return is_array($body) ? $body : [];
|
| }
|
|
|
| function gmt_osrm_distance_km($lat1, $lon1, $lat2, $lon2) {
|
| $url = sprintf(
|
| 'https://router.project-osrm.org/route/v1/driving/%F,%F;%F,%F?overview=false',
|
| $lon1, $lat1, $lon2, $lat2
|
| );
|
| $response = wp_remote_get($url, ['timeout' => 8]);
|
| if (is_wp_error($response)) return null;
|
| $body = json_decode(wp_remote_retrieve_body($response), true);
|
| if (empty($body['routes'][0]['distance'])) return null;
|
| return $body['routes'][0]['distance'] / 1000;
|
| }
|
|
|
| function gmt_get_distance_from_cergy(WP_REST_Request $request) {
|
| $city = sanitize_text_field($request->get_param('city'));
|
| $lat = $request->get_param('lat');
|
| $lon = $request->get_param('lon');
|
|
|
| if (empty($city)) {
|
| return new WP_Error('missing_city', 'Ville manquante.', ['status' => 400]);
|
| }
|
|
|
|
|
|
|
| if ($lat && $lon) {
|
| $cache_key = 'gmt_dist_' . gmt_slugify_city($city . '-' . $lat . '-' . $lon);
|
| $cached = get_option($cache_key);
|
| if ($cached) { $cached['cached'] = true; return rest_ensure_response($cached); }
|
|
|
| $km = gmt_osrm_distance_km(GMT_CERGY_LAT, GMT_CERGY_LON, (float) $lat, (float) $lon);
|
| if ($km === null) {
|
| return new WP_Error('routing_failed', "Impossible de calculer la distance routière.", ['status' => 502]);
|
| }
|
| $result = ['city' => $city, 'distance_km' => round($km, 1), 'cached' => false];
|
| update_option($cache_key, $result, false);
|
| return rest_ensure_response($result);
|
| }
|
|
|
|
|
| $cache_key = 'gmt_dist_' . gmt_slugify_city($city);
|
| $cached = get_option($cache_key);
|
| if ($cached && empty($cached['ambiguous'])) {
|
| $cached['cached'] = true;
|
| return rest_ensure_response($cached);
|
| }
|
|
|
| $results = gmt_nominatim_search($city . ', France');
|
| if (empty($results)) {
|
| return new WP_Error('city_not_found', "Ville introuvable. Vérifiez l'orthographe.", ['status' => 404]);
|
| }
|
|
|
|
|
|
|
| $place_types = ['city', 'town', 'village', 'municipality', 'hamlet'];
|
| $filtered = array_values(array_filter($results, function ($r) use ($place_types) {
|
| return in_array($r['type'] ?? '', $place_types, true);
|
| }));
|
| if (count($filtered) >= 1) $results = $filtered;
|
|
|
| if (count($results) > 1) {
|
| $options = array_map(function ($r) {
|
| return ['label' => $r['display_name'], 'lat' => $r['lat'], 'lon' => $r['lon']];
|
| }, array_slice($results, 0, 5));
|
| $result = ['ambiguous' => true, 'options' => $options];
|
| update_option($cache_key, $result, false);
|
| return rest_ensure_response($result);
|
| }
|
|
|
| $lat = (float) $results[0]['lat'];
|
| $lon = (float) $results[0]['lon'];
|
| $km = gmt_osrm_distance_km(GMT_CERGY_LAT, GMT_CERGY_LON, $lat, $lon);
|
| if ($km === null) {
|
| return new WP_Error('routing_failed', "Impossible de calculer la distance routière.", ['status' => 502]);
|
| }
|
|
|
| $result = [
|
| 'city' => $city,
|
| 'matched_label' => $results[0]['display_name'],
|
| 'distance_km' => round($km, 1),
|
| 'cached' => false,
|
| ];
|
| update_option($cache_key, $result, false);
|
| return rest_ensure_response($result);
|
| }
|
| |
| |
Comments