Files
Siro/backend/Admin/rides/admin_get_rides_by_phone.php
Hamza-Ayed 72eeb24cd7 Fix #18: Exception leak remediation across 87 PHP files
- Replaced all client-facing $e->getMessage() with generic error messages
- Added error_log() with filename prefix to all catch blocks
- Covered jsonError(), echo, and json_encode() response patterns
- Also fixed 2 remaining display_errors=1 and add_invoice.php leak
- Script-assisted fix for 75 files, manual fix for 12 remaining edge cases
2026-06-17 07:48:31 +03:00

184 lines
6.3 KiB
PHP

<?php
require_once __DIR__ . '/../../connect.php';
if ($role !== 'admin' && $role !== 'super_admin') {
http_response_code(403);
echo json_encode(['error' => 'Unauthorized: Admin access required']);
exit;
}
/**
* تطبيع رقم الهاتف ليتوافق مع التخزين في قاعدة البيانات
*/
function normalizePhone($phone) {
$clean = preg_replace('/\D+/', '', $phone);
// Syria: 099XXXXXXX or 9639XXXXXXX
if (strlen($clean) === 10 && strpos($clean, '09') === 0) return '963' . substr($clean, 1);
if (strlen($clean) === 12 && strpos($clean, '963') === 0) return $clean;
if (strlen($clean) === 9 && strpos($clean, '9') === 0) return '963' . $clean;
// Jordan: 079XXXXXXX or 9627XXXXXXX
if (strlen($clean) === 10 && strpos($clean, '07') === 0) return '962' . substr($clean, 1);
if (strlen($clean) === 12 && strpos($clean, '962') === 0) return $clean;
if (strlen($clean) === 9 && strpos($clean, '7') === 0) return '962' . $clean;
// Egypt: 010XXXXXXXX or 2010XXXXXXXX
if (strlen($clean) === 11 && strpos($clean, '01') === 0) return '20' . substr($clean, 1);
if (strlen($clean) === 13 && strpos($clean, '20') === 0) return $clean;
return $clean;
}
$phone = filterRequest('phone');
if (!$phone) {
error_log("[get_last_ride] Missing phone parameter");
jsonError("Phone is required");
exit;
}
// تطبيع الرقم أولاً
$raw = normalizePhone($phone);
// شَفِّر قبل الاستعلام
$enc_raw = $encryptionHelper->encryptData($raw);
try {
error_log("[get_last_ride] Searching phone normalized=$raw");
// 1) ابحث عن الراكب بالهاتف المشفّر
$selP = $con->prepare("
SELECT id, first_name, last_name, phone
FROM passengers
WHERE phone = :enc_raw
LIMIT 1
");
$selP->execute(['enc_raw' => $enc_raw]);
$passenger = $selP->fetch(PDO::FETCH_ASSOC);
// 2) ابحث عن السائق بالهاتف المشفّر
$selD = $con->prepare("
SELECT id AS driverID, first_name, last_name, phone
FROM driver
WHERE phone = :enc_raw
LIMIT 1
");
$selD->execute(['enc_raw' => $enc_raw]);
$driver = $selD->fetch(PDO::FETCH_ASSOC);
$userId = null;
$userType = null;
if ($passenger) {
$userId = $passenger['id'];
$userType = 'passenger';
error_log("[get_last_ride] Passenger found id=" . $userId);
}
if ($driver) {
$userId = $driver['driverID'];
$userType = 'driver';
error_log("[get_last_ride] Driver found id=" . $userId);
}
if (!$userId) {
error_log("[get_last_ride] User not found (phone=$raw)");
jsonError('Phone number not found in system');
exit;
}
// 3) تحديد حقل البحث في الرحلة
$userField = ($userType === 'driver') ? 'r.driver_id' : 'r.passenger_id';
// فلترة حسب الحالة إذا أُرسلت
$filterStatus = filterRequest('status');
$whereExtra = '';
$params = [':uid' => $userId];
if (!empty($filterStatus) && $filterStatus !== 'all') {
$whereExtra = "AND r.status = :filter_status";
$params[':filter_status'] = $filterStatus;
}
// 4) آخر 20 رحلة لهذا المستخدم
$rideStmt = $con->prepare("
SELECT
r.id,
r.start_location,
r.end_location,
r.date,
r.time,
r.endtime,
r.status,
r.paymentMethod,
r.carType,
r.price,
r.price_for_driver,
r.price_for_passenger,
r.distance,
r.driver_id,
r.passenger_id,
r.created_at,
r.updated_at,
r.DriverIsGoingToPassenger,
r.rideTimeStart,
r.rideTimeFinish,
d.first_name AS driver_first_name,
d.last_name AS driver_last_name,
d.phone AS d_phone,
p.first_name AS p_fname,
p.last_name AS p_lname,
p.phone AS p_phone
FROM ride r
LEFT JOIN driver d ON d.id = r.driver_id
LEFT JOIN passengers p ON p.id = r.passenger_id
WHERE $userField = :uid $whereExtra
ORDER BY r.created_at DESC, r.id DESC
LIMIT 20
");
$rideStmt->execute($params);
$rides = $rideStmt->fetchAll(PDO::FETCH_ASSOC);
// 5) فك تشفير الأسماء
if ($passenger) {
$passenger['first_name'] = $encryptionHelper->decryptData($passenger['first_name']);
$passenger['last_name'] = $encryptionHelper->decryptData($passenger['last_name']);
$passenger['phone'] = $encryptionHelper->decryptData($passenger['phone']);
}
if ($driver) {
$driver['first_name'] = $encryptionHelper->decryptData($driver['first_name']);
$driver['last_name'] = $encryptionHelper->decryptData($driver['last_name']);
$driver['phone'] = $encryptionHelper->decryptData($driver['phone']);
}
foreach ($rides as &$ride) {
if (!empty($ride['driver_first_name'])) {
$ride['driver_first_name'] = $encryptionHelper->decryptData($ride['driver_first_name']);
}
if (!empty($ride['driver_last_name'])) {
$ride['driver_last_name'] = $encryptionHelper->decryptData($ride['driver_last_name']);
}
if (!empty($ride['d_phone'])) {
$ride['d_phone'] = $encryptionHelper->decryptData($ride['d_phone']);
}
if (!empty($ride['p_fname'])) {
$ride['p_fname'] = $encryptionHelper->decryptData($ride['p_fname']);
}
if (!empty($ride['p_lname'])) {
$ride['p_lname'] = $encryptionHelper->decryptData($ride['p_lname']);
}
if (!empty($ride['p_phone'])) {
$ride['p_phone'] = $encryptionHelper->decryptData($ride['p_phone']);
}
}
unset($ride);
// 6) الرد
$response = [
'user_type' => $userType,
'user' => $userType === 'driver' ? $driver : $passenger,
'rides' => $rides
];
error_log("[get_last_ride] Success response for " . $userType . " id=" . $userId);
jsonSuccess($response);
} catch (Throwable $e) {
error_log("[get_last_ride] Exception: " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}