نسخة كاملة من مستودع سيرو عند ecfe7568 لتكون أساس تطبيق «انطلق». نُسخ المتعقَّب في git فقط (12,509 ملفاً / 302 م.ب) بـ git archive، لا `cp -r` — فاستُثنيت تلقائياً مخلفات البناء (build · node_modules · .dart_tool · .gradle · Pods ≈ 10.7 غ.ب) وكل ما يستثنيه .gitignore. هذا الكوميت **بلا أي تعديل عمداً** حتى يكون كل ما يليه فرقاً مقروءاً مقابل سيرو الأصلي. سيرو نفسه لم يُمسّ. ⚠️ لا يبني بعد: `.env` و`lib/env/env.g.dart` غير متعقَّبين في سيرو (وهذا صحيح — أسرار لكل مستأجر). كل تطبيق فلاتر هنا يحتاج .env خاصاً بانطلق ثم توليد env.g.dart عبر build_runner. لا تُنسخ أسرار سيرو. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
97 lines
4.1 KiB
PHP
97 lines
4.1 KiB
PHP
<?php
|
|
// cron_ride_timeout.php
|
|
// 🔥 أُعيدت كتابته بالكامل: كان يعتمد على جدول waitingRides الذي لم يعد
|
|
// يُملأ من تدفق add_ride.php الحقيقي (addWaitingRide.php لا يُستدعى من هناك)،
|
|
// فكانت الرحلات العالقة بحالة 'waiting' لا تُصفَّر أبداً. الآن يعمل مباشرة
|
|
// على جدول ride باستخدام أعمدة date/time المكتوبة فعلياً عند الإنشاء.
|
|
|
|
require_once __DIR__ . '/../../core/bootstrap.php';
|
|
require_once __DIR__ . '/../../functions.php';
|
|
|
|
error_log("⏰ [Cleanup Cron] Started cleaning old waiting rides...");
|
|
|
|
$minutesLimit = 15;
|
|
|
|
try {
|
|
$con = Database::get('main');
|
|
|
|
// =========================================================
|
|
// الخطوة 1: جلب الرحلات العالقة (status='waiting' منذ أكثر من 15 دقيقة)
|
|
// =========================================================
|
|
$sqlSelect = "SELECT id, passenger_id FROM ride
|
|
WHERE status = 'waiting'
|
|
AND TIMESTAMP(`date`, `time`) < DATE_SUB(NOW(), INTERVAL $minutesLimit MINUTE)";
|
|
$stmtSelect = $con->prepare($sqlSelect);
|
|
$stmtSelect->execute();
|
|
$staleRides = $stmtSelect->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$updatedCount = 0;
|
|
|
|
if (!empty($staleRides)) {
|
|
$sqlUpdate = "UPDATE ride SET status = 'timeout', updated_at = NOW() WHERE id = ? AND status = 'waiting'";
|
|
$stmtUpdate = $con->prepare($sqlUpdate);
|
|
|
|
// نسخة أرشيفية (best-effort)
|
|
$con_ride = null;
|
|
try {
|
|
$con_ride = Database::get('ride');
|
|
} catch (Exception $e) {
|
|
error_log("[cron_ride_timeout] Secondary ride DB unavailable: " . $e->getMessage());
|
|
}
|
|
$stmtUpdate2 = $con_ride ? $con_ride->prepare(
|
|
"UPDATE ride SET status = 'timeout', updated_at = NOW() WHERE id = ? AND status = 'waiting'"
|
|
) : null;
|
|
|
|
foreach ($staleRides as $ride) {
|
|
$rideId = $ride['id'];
|
|
|
|
$stmtUpdate->execute([$rideId]);
|
|
$updatedCount += $stmtUpdate->rowCount();
|
|
|
|
if ($stmtUpdate2) {
|
|
try {
|
|
$stmtUpdate2->execute([$rideId]);
|
|
} catch (PDOException $e) {
|
|
error_log("[cron_ride_timeout] Secondary DB update failed for #$rideId: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// 🆕 تنظيف Redis + إعلام أي سائقين ما زالوا يرون هذا الطلب على أنه ملغى
|
|
sendToLocationServer('cancel_ride', [
|
|
'ride_id' => $rideId,
|
|
'driver_id' => 0,
|
|
'reason' => 'timeout',
|
|
]);
|
|
}
|
|
}
|
|
|
|
// =========================================================
|
|
// الخطوة 2: تنظيف جدول waitingRides القديم (إن وُجدت صفوف فيه من مسار قديم)
|
|
// =========================================================
|
|
$deletedCount = 0;
|
|
try {
|
|
$sqlDelete = "DELETE FROM waitingRides WHERE created_at < DATE_SUB(NOW(), INTERVAL $minutesLimit MINUTE)";
|
|
$stmtDelete = $con->prepare($sqlDelete);
|
|
$stmtDelete->execute();
|
|
$deletedCount = $stmtDelete->rowCount();
|
|
} catch (PDOException $e) {
|
|
error_log("[cron_ride_timeout] waitingRides cleanup skipped: " . $e->getMessage());
|
|
}
|
|
|
|
if ($updatedCount > 0 || $deletedCount > 0) {
|
|
$msg = "✅ [Cleanup Cron] Success: Timed out $updatedCount ride(s) in ride table, and cleaned $deletedCount legacy waitingRides row(s).";
|
|
error_log($msg);
|
|
echo json_encode(["status" => "success", "message" => $msg]);
|
|
} else {
|
|
$msg = "💤 [Cleanup Cron] No expired rides found.";
|
|
error_log($msg);
|
|
echo json_encode(["status" => "success", "message" => "Nothing to clean."]);
|
|
}
|
|
|
|
} catch (PDOException $e) {
|
|
$errorMsg = "❌ [Cleanup Cron] Error: " . $e->getMessage();
|
|
error_log($errorMsg);
|
|
echo json_encode(["status" => "failure", "message" => "An internal error occurred."]);
|
|
}
|
|
?>
|