Files
intaleq/backend/ride/location/get.php
T

221 lines
9.2 KiB
PHP

<?php
// get.php (Main Server)
// 1. تضمين ملف الاتصال والدوال المساعدة (مهم جداً)
require_once __DIR__ . '/../../connect.php';
// ضبط التوقيت (للسجلات فقط، قاعدة البيانات تبقى UTC)
// date_default_timezone_set('Asia/Amman');
try {
// ==========================================
// 1. استقبال الإحداثيات (دعم الطريقتين)
// ==========================================
$lat = filterRequest("lat");
$lng = filterRequest("lng");
// دعم Bounds القديم (تحويله لمركز وقطر)
if (!$lat || !$lng) {
$swLat = filterRequest("southwestLat"); $neLat = filterRequest("northeastLat");
$swLon = filterRequest("southwestLon"); $neLon = filterRequest("northeastLon");
if ($swLat && $neLat && $swLon && $neLon) {
$lat = ($swLat + $neLat) / 2;
$lng = ($swLon + $neLon) / 2;
} else {
jsonError("Invalid coordinates provided");
exit;
}
}
// ==========================================
// 2. طلب بيانات السائقين من سيرفر اللوكيشن (Redis API)
// — يرجع cache hits لو موجودة، وإلا يرجع IDs فقط
// ==========================================
$locationServerUrl = getenv('LOCATION_API_URL') ?: 'https://api.intaleqapp.com/loction_server/api_get_nearby.php';
$keyPath = getenv('INTERNAL_SOCKET_KEY_PATH') ?: '/keys/.internal_socket_key';
$INTERNAL_KEY = getenv('INTERNAL_SOCKET_KEY') ?: (file_exists($keyPath) ? trim((string)@file_get_contents($keyPath)) : (file_exists(__DIR__ . '/../../../loction-keys/.internal_socket_key') ? trim((string)@file_get_contents(__DIR__ . '/../../../loction-keys/.internal_socket_key')) : (file_exists('/home/location/.internal_socket_key') ? trim((string)@file_get_contents('/home/location/.internal_socket_key')) : '')));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $locationServerUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
'lat' => $lat,
'lng' => $lng,
'radius' => 5,
'limit' => 50
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-internal-key: $INTERNAL_KEY"]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
error_log("[get.php] api_get_nearby HTTP $httpCode | Response: $response");
$redisDrivers = [];
if ($httpCode == 200 && $response) {
$json = json_decode($response, true);
if (isset($json['status']) && $json['status'] === true) {
$redisDrivers = $json['drivers'] ?? $json['data'] ?? [];
} else {
error_log("[get.php] api_get_nearby returned error or false status. JSON: " . print_r($json, true));
}
} else {
error_log("[get.php] api_get_nearby failed. HTTP Code: $httpCode");
}
if (empty($redisDrivers)) {
jsonSuccess([]);
exit;
}
// تقسيم: cache hits → نستخدمها فوراً، cache misses → نحتاج MySQL
$final_result = [];
$mysqlIds = [];
$driversMap = [];
$serverNow = date('Y-m-d H:i:s');
foreach ($redisDrivers as $d) {
$driverId = $d['driver_id'] ?? $d['id'] ?? null;
if (!$driverId) continue;
if (!empty($d['cached']) && !empty($d['first_name'])) {
// ✅ Cache hit — بيانات السائق كاملة من Redis, نستخدمها مباشرة
$d['serverNow'] = $serverNow;
$final_result[] = $d;
} else {
// ❌ Cache miss — نحتاج نجيب البيانات من MySQL
$mysqlIds[] = $driverId;
$driversMap[$driverId] = $d;
}
}
// ==========================================
// 3. فقط للسائقين اللي ما فيهم Cache: MySQL
// ==========================================
if (!empty($mysqlIds)) {
$placeholders = implode(',', array_fill(0, count($mysqlIds), '?'));
$sql_drivers_info = "
SELECT
d.id AS driver_id,
d.phone, d.email, d.birthdate, d.first_name, d.last_name, d.gender, d.maritalStatus,
cr.make, cr.car_plate, cr.model, cr.color, cr.vin, cr.color_hex, cr.year, cr.vehicle_category_id,
dt.token,
COALESCE(rdAvg.ratingDriver, 0) AS ratingDriver
FROM driver d
LEFT JOIN CarRegistration cr ON cr.driverID = d.id
LEFT JOIN driverToken dt ON dt.captain_id = d.id
LEFT JOIN (
SELECT driver_id, AVG(rating) AS ratingDriver FROM ratingDriver GROUP BY driver_id
) rdAvg ON rdAvg.driver_id = d.id
WHERE d.id IN ($placeholders)
";
$stmt = $con->prepare($sql_drivers_info);
$stmt->execute($mysqlIds);
$drivers_db = $stmt->fetchAll(PDO::FETCH_ASSOC);
$fieldsToDecrypt = ['phone','email','gender','birthdate','first_name','last_name','token','car_plate','vin'];
$foundIds = [];
foreach ($drivers_db as $row) {
$did = $row['driver_id'];
$foundIds[] = $did;
if (isset($driversMap[$did])) {
$redisInfo = $driversMap[$did];
$row['latitude'] = $redisInfo['latitude'] ?? $redisInfo['lat'] ?? '';
$row['longitude'] = $redisInfo['longitude'] ?? $redisInfo['lng'] ?? '';
$row['heading'] = $redisInfo['heading'] ?? '0';
$row['speed'] = $redisInfo['speed'] ?? '0';
} else {
continue;
}
$row['serverNow'] = $serverNow;
foreach ($fieldsToDecrypt as $field) {
if (isset($row[$field]) && $row[$field] !== null && $row[$field] !== '') {
try {
$decrypted = $encryptionHelper->decryptData($row[$field]);
if ($decrypted !== false && $decrypted !== null) {
$row[$field] = $decrypted;
}
} catch (Throwable $e) {
// Keep original value if decryption fails
}
}
}
if (!empty($row['birthdate'])) {
try {
$birthdate = new DateTime($row['birthdate']);
$today = new DateTime();
$row['age'] = $today->diff($birthdate)->y;
} catch (Exception $e) { $row['age'] = null; }
} else {
$row['age'] = null;
}
$final_result[] = $row;
// 🆕 Fill driver:public cache for next time (async, fire-and-forget)
sendToLocationServer('cache_driver_public', [
'driver_id' => $did,
'data' => json_encode([
'first_name' => $row['first_name'] ?? '',
'last_name' => $row['last_name'] ?? '',
'gender' => $row['gender'] ?? '',
'make' => $row['make'] ?? '',
'model' => $row['model'] ?? '',
'color' => $row['color'] ?? '',
'color_hex' => $row['color_hex'] ?? '',
'year' => $row['year'] ?? '',
'car_plate' => $row['car_plate'] ?? '',
'ratingDriver'=> $row['ratingDriver'] ?? '0',
'latitude' => $row['latitude'] ?? '',
'longitude' => $row['longitude'] ?? '',
'heading' => $row['heading'] ?? '0',
'speed' => $row['speed'] ?? '0',
'updated_at' => time()
]),
]);
}
// 🚀 Fallback: إذا كان السائق نشط في Redis لكن بيانت السيارة في MySQL مفقودة/قديمة، أظهر موقعه للراكب
$missingIds = array_diff($mysqlIds, $foundIds);
foreach ($missingIds as $mid) {
if (isset($driversMap[$mid])) {
$d = $driversMap[$mid];
$final_result[] = [
'driver_id' => $mid,
'id' => $mid,
'first_name'=> 'Driver',
'last_name' => '',
'latitude' => $d['latitude'] ?? $d['lat'] ?? '',
'longitude' => $d['longitude'] ?? $d['lng'] ?? '',
'heading' => $d['heading'] ?? '0',
'speed' => $d['speed'] ?? '0',
'make' => '',
'model' => '',
'serverNow' => $serverNow,
];
}
}
}
// إرجاع النتيجة
jsonSuccess($final_result);
} catch (PDOException $e) {
error_log("[get.php] " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
} catch (Throwable $e) {
error_log("[get.php] " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}
?>