'failure', 'message' => 'Unauthorized. Driver role required.']); exit; } // 2. Filter Inputs $action = filterRequest('action') ?? 'set'; $destLat = filterRequest('destination_lat') ?? filterRequest('target_latitude'); $destLng = filterRequest('destination_lng') ?? filterRequest('target_longitude'); $destName = filterRequest('destination_name') ?? 'Destination'; function notifySocketServerDestination($userId, $hasDestination, $destLat = '', $destLng = '', $destName = '') { $url = getenv('LOCATION_SOCKET_URL'); $internalKey = function_exists('getInternalSocketKey') ? getInternalSocketKey() : ''; if (empty($url)) { error_log("[save_driver_destination] LOCATION_SOCKET_URL env variable not set"); return; } $postData = [ 'action' => 'update_driver_destination', 'driver_id' => (string)$userId, 'has_destination' => (int)$hasDestination, 'destination_lat' => (string)$destLat, 'destination_lng' => (string)$destLng, 'destination_name' => (string)$destName, ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT_MS, 400); if ($internalKey) { curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-internal-key: $internalKey"]); } curl_exec($ch); curl_close($ch); } try { if ($action === 'get') { $stmtGet = $con->prepare(" SELECT target_latitude, target_longitude, destination_name, created_at FROM driver_destinations WHERE driver_id = :did AND is_active = 1 LIMIT 1 "); $stmtGet->execute([':did' => $user_id]); $activeDest = $stmtGet->fetch(PDO::FETCH_ASSOC); if ($activeDest) { jsonSuccess($activeDest, "Active destination retrieved."); } else { jsonSuccess(null, "No active destination set."); } exit; } if ($action === 'clear') { $stmtDeactivate = $con->prepare(" UPDATE driver_destinations SET is_active = 0 WHERE driver_id = :did AND is_active = 1 "); $stmtDeactivate->execute([':did' => $user_id]); // Sync with Redis on Socket Server notifySocketServerDestination($user_id, 0); jsonSuccess(null, "تم إلغاء تفعيل الوجهة الشخصية بنجاح."); exit; } // Default action: set if (empty($destLat) || empty($destLng)) { jsonError("Missing required parameters: destination_lat and destination_lng are required."); } // 3. Enforce Limit: Max 3 times daily // Check local Redis rate limit first if (isset($redis)) { $redisKey = "driver:dest_count:" . $user_id; $redisCount = intval($redis->get($redisKey)); if ($redisCount >= 3) { jsonError("حسناً كابتن، لقد وصلت للحد الأقصى المسموح به لتحديد الوجهة اليوم (3 مرات في اليوم)."); } } // Check MySQL database limit $stmtCount = $con->prepare(" SELECT COUNT(*) FROM driver_destinations WHERE driver_id = :did AND usage_date = CURDATE() "); $stmtCount->execute([':did' => $user_id]); $dailyCount = intval($stmtCount->fetchColumn()); if ($dailyCount >= 3) { // Sync Redis counter just in case if (isset($redis)) { $redisKey = "driver:dest_count:" . $user_id; $redis->set($redisKey, $dailyCount); $redis->expire($redisKey, 86400); // 24 hours TTL } jsonError("حسناً كابتن، لقد وصلت للحد الأقصى المسموح به لتحديد الوجهة اليوم (3 مرات في اليوم)."); } // 4. Deactivate previous active destinations for this driver $stmtDeactivate = $con->prepare(" UPDATE driver_destinations SET is_active = 0 WHERE driver_id = :did AND is_active = 1 "); $stmtDeactivate->execute([':did' => $user_id]); // 5. Insert new destination $stmtInsert = $con->prepare(" INSERT INTO driver_destinations (driver_id, target_latitude, target_longitude, destination_name, is_active, usage_date) VALUES (:did, :lat, :lng, :name, 1, CURDATE()) "); $stmtInsert->execute([ ':did' => $user_id, ':lat' => (float)$destLat, ':lng' => (float)$destLng, ':name' => $destName ]); // Sync with Redis on Socket Server notifySocketServerDestination($user_id, 1, $destLat, $destLng, $destName); // Increment local Redis counter if (isset($redis)) { $redisKey = "driver:dest_count:" . $user_id; $redis->incr($redisKey); $redis->expire($redisKey, 86400); // 24 hours TTL } jsonSuccess(null, "تم حفظ وجهتك كابتن بنجاح! سيتم توجيه الطلبات المطابقة لوجهتك."); } catch (Exception $e) { error_log("[save_driver_destination.php] Error: " . $e->getMessage()); jsonError("Failed to save driver destination: " . $e->getMessage()); }