Home / Admin / Calcul distance Cergy
Duplicate Snippet

Embed Snippet on Your Site

Calcul distance Cergy

Calcule la distance routière entre Cergy et la ville du client

Code Preview
php
<?php
<?php
/**
 * Green Multitech — Calcul de distance routière depuis Cergy (gratuit, sans clé API)
 * À coller dans WPCode > Ajouter un extrait > PHP Snippet > "Exécuter partout"
 */
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]);
    }
    // Cas 1 : l'utilisateur a choisi une ville dans une liste de désambiguïsation
    // -> on a déjà lat/lon, pas besoin de re-géocoder.
    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);
    }
    // Cas 2 : simple recherche par nom de ville
    $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]);
    }
    // On privilégie les résultats de type "ville/village" pour éviter le bruit
    // (quartiers, rues, etc.) avant de proposer une désambiguïsation.
    $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

Add a Comment