Initial commit with updated Auth and media ignored

This commit is contained in:
Hamza-Ayed
2026-04-28 13:04:27 +03:00
commit 67af97474c
477 changed files with 66444 additions and 0 deletions

View File

View File

View File

View File

@@ -0,0 +1,75 @@
<?php
require_once __DIR__ . '/../../connect.php';
$sql = "SELECT
`driver`.`id`,
`driver`.`phone`,
`driver`.`email`,
`driver`.`gender`,
`driver`.`status`,
`driver`.`birthdate`,
`driver`.`site`,
`driver`.`first_name`,
`driver`.`last_name`,
`driver`.`employmentType`,
`driver`.`maritalStatus`,
`driver`.`created_at`,
`driver`.`updated_at`,
(
SELECT COUNT(`driver`.`id`) FROM `driver`
) AS countPassenger,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10, 2))
FROM `ratingPassenger`
WHERE `ratingPassenger`.`driverID` = `driver`.`id`
) AS ratingPassenger,
(
SELECT COUNT(*) FROM `ratingPassenger` WHERE `driverID` = `driver`.`id`
) AS countDriverRate,
(
SELECT COUNT(*) FROM `canecl` WHERE `driverID` = `driver`.`id`
) AS countPassengerCancel,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10, 2))
FROM `ratingDriver`
WHERE `driver_id` = `driver`.`id`
) AS passengerAverageRating,
(
SELECT COUNT(*) FROM `ratingDriver` WHERE `driver_id` = `driver`.`id`
) AS countPassengerRate,
(
SELECT COUNT(*) FROM `ride` WHERE `driver_id` = `driver`.`id`
) AS countPassengerRide,
(
SELECT `token`
FROM `driverToken`
WHERE `captain_id` = `driver`.`id`
LIMIT 1
) AS passengerToken
FROM `driver`
ORDER BY passengerAverageRating DESC
LIMIT 10";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// فك تشفير الحقول الحساسة
foreach ($result as &$row) {
$row['phone'] = $encryptionHelper->decryptData($row['phone']);
$row['email'] = $encryptionHelper->decryptData($row['email']);
$row['gender'] = $encryptionHelper->decryptData($row['gender']);
$row['birthdate'] = $encryptionHelper->decryptData($row['birthdate']);
$row['site'] = $encryptionHelper->decryptData($row['site']);
$row['first_name'] = $encryptionHelper->decryptData($row['first_name']);
$row['last_name'] = $encryptionHelper->decryptData($row['last_name']);
$row['employmentType'] = $encryptionHelper->decryptData($row['employmentType']);
$row['maritalStatus'] = $encryptionHelper->decryptData($row['maritalStatus']);
}
if (count($result) > 0) {
jsonSuccess($result);
} else {
jsonError("No records found");
}
?>

View File

@@ -0,0 +1,86 @@
<?php
require_once __DIR__ . '/../../connect.php';
$driver_id = filterRequest("driver_id");
$driverEmail = $encryptionHelper->encryptData(filterRequest("driverEmail"));
$driverPhone = $encryptionHelper->encryptData(filterRequest("driverPhone"));
$sql = "SELECT
`driver`.`id`,
`driver`.`phone`,
`driver`.`email`,
`driver`.`gender`,
`driver`.`status`,
`driver`.`birthdate`,
`driver`.`site`,
`driver`.`first_name`,
`driver`.`last_name`,
`driver`.`education`,
`driver`.`employmentType`,
`driver`.`maritalStatus`,
`driver`.`created_at`,
`driver`.`updated_at`,
(
SELECT COUNT(*) FROM `driver`
) AS countPassenger,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10, 2))
FROM `ratingPassenger`
WHERE `ratingPassenger`.`driverID` = `driver`.`id`
) AS ratingPassenger,
(
SELECT COUNT(*) FROM `ratingPassenger` WHERE `driverID` = `driver`.`id`
) AS countDriverRate,
(
SELECT COUNT(*) FROM `canecl` WHERE `driverID` = `driver`.`id`
) AS countPassengerCancel,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10, 2))
FROM `ratingDriver`
WHERE `driver_id` = `driver`.`id`
) AS passengerAverageRating,
(
SELECT COUNT(*) FROM `ratingDriver` WHERE `driver_id` = `driver`.`id`
) AS countPassengerRate,
(
SELECT COUNT(*) FROM `ride` WHERE `driver_id` = `driver`.`id`
) AS countPassengerRide,
(
SELECT `token`
FROM `driverToken`
WHERE `captain_id` = `driver`.`id`
LIMIT 1
) AS passengerToken
FROM `driver`
WHERE `driver`.`email` = :email OR `driver`.`phone` = :phone OR `driver`.`id` = :id
ORDER BY passengerAverageRating DESC
LIMIT 10
";
$stmt = $con->prepare($sql);
$stmt->bindParam(":email", $driverEmail);
$stmt->bindParam(":phone", $driverPhone);
$stmt->bindParam(":id", $driver_id);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// فك تشفير الحقول الحساسة
foreach ($result as &$row) {
$row['phone'] = $encryptionHelper->decryptData($row['phone']);
$row['email'] = $encryptionHelper->decryptData($row['email']);
$row['gender'] = $encryptionHelper->decryptData($row['gender']);
$row['birthdate'] = $encryptionHelper->decryptData($row['birthdate']);
$row['site'] = $encryptionHelper->decryptData($row['site']);
$row['first_name'] = $encryptionHelper->decryptData($row['first_name']);
$row['last_name'] = $encryptionHelper->decryptData($row['last_name']);
$row['education'] = $encryptionHelper->decryptData($row['education']);
$row['employmentType'] = $encryptionHelper->decryptData($row['employmentType']);
$row['maritalStatus'] = $encryptionHelper->decryptData($row['maritalStatus']);
}
if ($stmt->rowCount() > 0) {
jsonSuccess($result);
} else {
jsonError("No records found");
}
?>

View File

@@ -0,0 +1,87 @@
<?php
require_once __DIR__ . '/../../connect.php';
// تشفير driver_id قبل استخدامه في SQL
$driver_id = filterRequest("driver_id");
$sql = "SELECT
`driver`.`id`,
`driver`.`phone`,
`driver`.`email`,
`driver`.`gender`,
`driver`.`status`,
`driver`.`birthdate`,
`driver`.`site`,
`driver`.`first_name`,
`driver`.`last_name`,
`driver`.`education`,
`driver`.`employmentType`,
`driver`.`maritalStatus`,
`driver`.`created_at`,
`driver`.`updated_at`,
(
SELECT COUNT(*) FROM `driver`
) AS countPassenger,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10, 2))
FROM `ratingPassenger`
WHERE `ratingPassenger`.`driverID` = `driver`.`id`
) AS ratingPassenger,
(
SELECT COUNT(*) FROM `ratingPassenger`
WHERE `ratingPassenger`.`driverID` = `driver`.`id`
) AS countDriverRate,
(
SELECT COUNT(*) FROM `canecl`
WHERE `canecl`.`driverID` = `driver`.`id`
) AS countPassengerCancel,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10, 2))
FROM `ratingDriver`
WHERE `ratingDriver`.`driver_id` = `driver`.`id`
) AS passengerAverageRating,
(
SELECT COUNT(*) FROM `ratingDriver`
WHERE `ratingDriver`.`driver_id` = `driver`.`id`
) AS countPassengerRate,
(
SELECT COUNT(*) FROM `ride`
WHERE `ride`.`driver_id` = `driver`.`id`
) AS countPassengerRide,
(
SELECT `token`
FROM `driverToken`
WHERE `driverToken`.`captain_id` = `driver`.`id`
LIMIT 1
) AS passengerToken
FROM `driver`
WHERE `driver`.`id` = :driver_id
ORDER BY passengerAverageRating DESC
LIMIT 10";
$stmt = $con->prepare($sql);
$stmt->bindParam(':driver_id', $driver_id);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// فك تشفير الحقول الحساسة بعد الجلب
foreach ($result as &$row) {
$row['phone'] = $encryptionHelper->decryptData($row['phone']);
$row['email'] = $encryptionHelper->decryptData($row['email']);
$row['gender'] = $encryptionHelper->decryptData($row['gender']);
$row['birthdate'] = $encryptionHelper->decryptData($row['birthdate']);
$row['site'] = $encryptionHelper->decryptData($row['site']);
$row['first_name'] = $encryptionHelper->decryptData($row['first_name']);
$row['last_name'] = $encryptionHelper->decryptData($row['last_name']);
$row['education'] = $encryptionHelper->decryptData($row['education']);
$row['employmentType'] = $encryptionHelper->decryptData($row['employmentType']);
$row['maritalStatus'] = $encryptionHelper->decryptData($row['maritalStatus']);
}
if ($stmt->rowCount() > 0) {
jsonSuccess($result);
} else {
jsonError("No records found");
}
?>

View File

@@ -0,0 +1,33 @@
<?php
require_once __DIR__ . '/../../connect.php';
$sql = "
SELECT
d.phone,
d.id,
d.name_arabic,
dt.token
FROM
`driver` d
LEFT JOIN driverToken dt ON
dt.captain_id = d.id
";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// فك التشفير للحقول الحساسة
foreach ($result as &$row) {
$row['phone'] = $encryptionHelper->decryptData($row['phone']);
if (!empty($row['token'])) {
$row['token'] = $encryptionHelper->decryptData($row['token']);
}
}
if ($stmt->rowCount() > 0) {
jsonSuccess($result);
} else {
jsonError("No records found");
}
?>

View File

79
Admin/AdminRide/get.php Normal file
View File

@@ -0,0 +1,79 @@
<?php
require_once __DIR__ . '/../../connect.php';
$sql = "SELECT
(
SELECT TIME_FORMAT(SEC_TO_TIME(AVG(TIMESTAMPDIFF(SECOND, rideTimeStart, rideTimeFinish))), '%Hh %im')
FROM ride
WHERE rideTimeStart IS NOT NULL AND rideTimeFinish IS NOT NULL
) AS driver_avg_duration,
(
SELECT COUNT(*) FROM (
SELECT COUNT(driver_id) FROM ride GROUP BY driver_id
) AS sub
) AS num_Driver,
(
SELECT COUNT(*) FROM ride
) AS total_rides,
(
SELECT COUNT(*) FROM ride WHERE status = 'waiting'
) AS ongoing_rides,
(
SELECT COUNT(*) FROM ride WHERE status = 'Finished'
) AS completed_rides,
(
SELECT COUNT(*) FROM ride WHERE status = 'cancelled'
) AS cancelled_rides,
(
SELECT TIME_FORMAT(SEC_TO_TIME(MAX(TIMESTAMPDIFF(SECOND, rideTimeStart, rideTimeFinish))), '%Hh %im')
FROM ride
WHERE rideTimeStart IS NOT NULL AND rideTimeFinish IS NOT NULL
) AS longest_duration,
(
SELECT ROUND(SUM(distance), 2) FROM ride
) AS total_distance,
(
SELECT ROUND(AVG(distance), 2) FROM ride
) AS average_distance,
(
SELECT ROUND(MAX(distance), 2) FROM ride
) AS longest_distance,
(
SELECT ROUND(SUM(price_for_driver), 2) FROM ride
) AS total_driver_earnings,
(
SELECT ROUND(SUM(price_for_passenger), 2) FROM ride
) AS total_company_earnings,
(
SELECT ROUND(
(SELECT SUM(price_for_passenger) FROM ride) /
NULLIF((SELECT SUM(price_for_driver) FROM ride), 0),
2
)
) AS companyPercent
FROM dual
LIMIT 1";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($stmt->rowCount() > 0) {
jsonSuccess($result);
} else {
jsonError("No records found");
}
?>

View File

@@ -0,0 +1,52 @@
<?php
require_once __DIR__ . '/../../connect.php';
$currentYear = date('Y');
$currentMonth = date('m');
// SQL to get daily ride counts
$sql = "
SELECT
YEAR(date) AS year,
MONTH(date) AS month,
DAY(date) AS day,
COUNT(*) AS rides_count
FROM
ride
GROUP BY
YEAR(date),
MONTH(date),
DAY(date)
ORDER BY
YEAR(date),
MONTH(date),
DAY(date)
";
$stmt = $con->prepare($sql);
$stmt->execute();
$dailyRides = $stmt->fetchAll(PDO::FETCH_ASSOC);
// SQL to get current month's total ride count
$sqlMonth = "
SELECT COUNT(*) AS current_month_rides_count
FROM ride
WHERE MONTH(date) = :currentMonth AND YEAR(date) = :currentYear
";
$stmtMonth = $con->prepare($sqlMonth);
$stmtMonth->bindParam(':currentMonth', $currentMonth);
$stmtMonth->bindParam(':currentYear', $currentYear);
$stmtMonth->execute();
$monthRides = $stmtMonth->fetch(PDO::FETCH_ASSOC);
// Append current month total to each row (if needed)
foreach ($dailyRides as &$row) {
$row['current_month_rides_count'] = $monthRides['current_month_rides_count'];
}
// Return result
if ($dailyRides) {
jsonSuccess($dailyRides);
} else {
jsonError("No records found");
}
?>

25
Admin/adminUser/add.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
require_once __DIR__ . '/../../connect.php';
$deviceNumber = filterRequest("deviceNumber"); // Assuming you'll get deviceNumber as input
$name = filterRequest("name");
$sql = "INSERT INTO `adminUser`(`id`, `device_number`, `name`) VALUES (
UUID(),
:deviceNumber,
:name
)";
$stmt = $con->prepare($sql);
$stmt->bindParam(':deviceNumber', $deviceNumber);
$stmt->bindParam(':name', $name);
$stmt->execute();
if ($stmt->rowCount() > 0) {
// Print a success message
jsonSuccess($message = "Admin user data saved successfully");
} else {
// Print a failure message
jsonError($message = "Failed to save admin user data");
}
?>

75
Admin/adminUser/add_invoice.php Executable file
View File

@@ -0,0 +1,75 @@
<?php
// عرض كافة الأخطاء
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once __DIR__ . '/../../connect.php';
$driverID = filterRequest("driverID");
$invoiceNumber = filterRequest("invoiceNumber");
$amount = filterRequest("amount");
$date = filterRequest("date");
$name = filterRequest("name");
$linkImage = null;
$uploadDate = date("Y-m-d H:i:s");
// ✅ طباعة بيانات الإدخال للتأكد
error_log("[add_invoice.php] 📥 Data received | driverID: $driverID, invoiceNumber: $invoiceNumber, amount: $amount, date: $date");
// التحقق من وجود ملف الصورة
if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) {
$image_file = $_FILES['image'];
$image_name = $image_file['name'];
$image_extension = strtolower(pathinfo($image_name, PATHINFO_EXTENSION));
$allowed_extensions = ['jpg', 'jpeg', 'png'];
if (!in_array($image_extension, $allowed_extensions)) {
error_log("[add_invoice.php] ❌ Invalid image extension: .$image_extension");
echo json_encode(['status' => 'error', 'message' => 'Invalid file type.']);
exit;
}
$new_filename = $invoiceNumber . "_" . $driverID . '.' . $image_extension;
$target_dir = "invoice_images/";
$target_file = $target_dir . $new_filename;
if (!is_dir($target_dir)) {
if (!mkdir($target_dir, 0755, true)) {
error_log("[add_invoice.php] ❌ Failed to create directory: $target_dir");
}
}
if (!move_uploaded_file($image_file['tmp_name'], $target_file)) {
error_log("[add_invoice.php] ❌ Failed to move uploaded file.");
echo json_encode(['status' => 'error', 'message' => 'Failed to upload image.']);
exit;
}
$linkImage = 'https://intaleq.xyz/intaleq/Admin/adminUser/invoice_images/' . $new_filename;
error_log("[add_invoice.php] ✅ Image uploaded successfully: $linkImage");
}
try {
$stmt = $con->prepare("INSERT INTO invoice_records (driverID, invoice_number,name, amount, date, image_link, created_at)
VALUES (?, ?, ?,?, ?, ?, ?)");
$stmt->execute([$driverID, $invoiceNumber,$name, $amount, $date, $linkImage, $uploadDate]);
echo json_encode([
'status' => 'success',
'message' => 'Invoice data saved.',
'image' => $linkImage
]);
error_log("[add_invoice.php] ✅ Invoice saved successfully.");
} catch (PDOException $e) {
$errorMsg = $e->getMessage();
error_log("[add_invoice.php] 🛑 PDO ERROR: $errorMsg");
echo json_encode([
'status' => 'error',
'message' => "Database error: $errorMsg"
]);
}

View File

View File

24
Admin/adminUser/get.php Normal file
View File

@@ -0,0 +1,24 @@
<?php
require_once __DIR__ . '/../../connect.php';
$device_number = filterRequest("device_number");
$sql = "SELECT
*
FROM
`adminUser`
WHERE
`device_number` = '$device_number'";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (count($result) === 1) {
// Print the first record as a success message
jsonSuccess($result[0]);
} else {
// Print a failure message
jsonError($message = "Failed to retrieve Password or user name incorrect");
}
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

View File

@@ -0,0 +1,28 @@
<?php
require_once __DIR__ . '/../../connect.php';
// ✅ استرجاع كل الفواتير من قاعدة البيانات
try {
$stmt = $con->prepare("SELECT * FROM invoice_records ORDER BY date DESC");
$stmt->execute();
$invoices = $stmt->fetchAll(PDO::FETCH_ASSOC);
// ✅ حساب عدد الفواتير ومجموع المبالغ
$count = count($invoices);
$totalAmount = array_sum(array_column($invoices, 'amount'));
echo json_encode([
"status" => "success",
"data" => $invoices,
"summary" => [
"count" => $count,
"total" => $totalAmount
]
]);
} catch (PDOException $e) {
echo json_encode([
"status" => "error",
"message" => "Database error: " . $e->getMessage()
]);
}
?>

View File

26
Admin/auth/login.php Executable file
View File

@@ -0,0 +1,26 @@
<?php
//login.php
require_once __DIR__ . '/../../connect.php';
$device = filterRequest("device_number");
$phone = filterRequest("phone_number");
if (empty($device) || empty($phone)) {
jsonError("device_number أو phone_number مفقود");
exit;
}
$stmt = $con->prepare("SELECT * FROM adminUser WHERE device_number = ? AND name = ?");
$stmt->execute([$device, $phone]);
if ($stmt->rowCount() > 0) {
$admin = $stmt->fetch(PDO::FETCH_ASSOC);
// يمكن لاحقًا توليد توكن أو بيانات أخرى
printSuccess([
"message" => "تم التحقق بنجاح",
"admin" => $admin,
]);
} else {
jsonError("بيانات الدخول غير صحيحة أو غير مسجلة.");
}

56
Admin/auth/send_otp_admin.php Executable file
View File

@@ -0,0 +1,56 @@
<?php
// send_otp_admin.php — إرسال رمز التحقق لمسؤول عبر WhatsApp
require_once __DIR__ . '/../../connect.php';
error_log("--- [send_otp_admin] Script started ---");
// جلب الرقم من الطلب
$receiver = filterRequest("receiver");
//error_log("[send_otp_admin] Received phone number: " . var_export($receiver, true));
if (!$receiver) {
// error_log("[send_otp_admin] Missing phone number");
jsonError("رقم الهاتف مفقود.");
exit;
}
// قراءة الأرقام المصرح بها من ENV
$allowedPhones = explode(',', getenv('ADMIN_PHONE_NUMBERS'));
//error_log("[send_otp_admin] Allowed phones: " . implode(', ', $allowedPhones));
if (!in_array($receiver, $allowedPhones)) {
error_log("[send_otp_admin] Unauthorized phone number attempted: $receiver");
jsonError("رقم الهاتف غير مصرح له.");
exit;
}
// توليد رمز تحقق عشوائي
$otp = rand(10000, 99999);
$messageBody = "رمز التحقق الخاص بك للدخول إلى لوحة الإدارة هو: $otp";
//error_log("[send_otp_admin] Generated OTP: $otp for $receiver");
// إرسال الرسالة عبر WhatsApp
$success = sendWhatsAppFromServer($receiver, $messageBody);
error_log("[send_otp_admin] WhatsApp sending result: " . ($success ? "success" : "failure"));
if ($success) {
try {
$stmt = $con->prepare("INSERT INTO token_verification_admin (phone_number, token, expiration_time)
VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 5 MINUTE))
ON DUPLICATE KEY UPDATE token = VALUES(token), expiration_time = VALUES(expiration_time)");
$stmt->execute([$receiver, $otp]);
// error_log("[send_otp_admin] OTP saved to database successfully for $receiver");
jsonSuccess(null, "OTP sent successfully.");
} catch (PDOException $e) {
// error_log("[send_otp_admin] Database error: " . $e->getMessage());
jsonError("حدث خطأ في حفظ الرمز.");
}
} else {
// error_log("[send_otp_admin] Failed to send WhatsApp message to $receiver");
jsonError("فشل في إرسال الرمز عبر WhatsApp.");
}
//error_log("--- [send_otp_admin] Script ended ---");
?>

46
Admin/auth/verify_otp_admin.php Executable file
View File

@@ -0,0 +1,46 @@
<?php
require_once __DIR__ . '/../../connect.php';
$phone = filterRequest("phone_number");
$otp = filterRequest("otp");
$deviceNumber = filterRequest("device_number");
if (empty($phone) || empty($otp)) {
jsonError("رقم الهاتف أو رمز التحقق مفقود.");
exit;
}
// التحقق من رمز التحقق (OTP)
$stmt = $con->prepare("SELECT * FROM token_verification_admin
WHERE phone_number = ? AND token = ?
AND expiration_time >= NOW()");
$stmt->execute([$phone, $otp]);
if ($stmt->rowCount() > 0) {
// ✅ تحقق ناجح - ننتقل إلى إدخال أو تحديث سجل adminUser
// تحقق إن كان المستخدم موجود مسبقًا
$checkAdmin = $con->prepare("SELECT * FROM adminUser WHERE name = ?");
$checkAdmin->execute([$phone]);
$now = date("Y-m-d H:i:s");
if ($checkAdmin->rowCount() > 0) {
// المستخدم موجود ✅ تحديث device_number و updated_at
$update = $con->prepare("UPDATE adminUser
SET device_number = ?, updated_at = ?
WHERE name = ?");
$update->execute([$deviceNumber, $now, $phone]);
jsonSuccess(["message" => "verified and updated existing admin"]);
} else {
// المستخدم غير موجود ✅ إدخال جديد
$insert = $con->prepare("INSERT INTO adminUser (device_number, name, created_at, updated_at)
VALUES (?, ?, ?, ?)");
$insert->execute([$deviceNumber, $phone, $now, $now]);
jsonSuccess(["message" => "verified and new admin created"]);
}
} else {
// ❌ رمز التحقق غير صالح
jsonError("رمز التحقق غير صالح أو منتهي.");
}

69
Admin/dashbord.php Normal file
View File

@@ -0,0 +1,69 @@
<?php
require_once __DIR__ . '/../connect.php';
$sql = "
SELECT
-- العدادات العامة
(SELECT COUNT(*) FROM passengers) AS countPassengers,
(SELECT COUNT(*) FROM driver) AS countDriver,
(SELECT COUNT(*) FROM ride) AS countRide,
-- إحصائيات الشهر الحالي
(SELECT COUNT(*) FROM passengers WHERE created_at BETWEEN DATE_FORMAT(CURDATE(), '%Y-%m-01') AND LAST_DAY(CURDATE())) AS countPassengersThisMonth,
(SELECT COUNT(*) FROM driver WHERE created_at BETWEEN DATE_FORMAT(CURDATE(), '%Y-%m-01') AND LAST_DAY(CURDATE())) AS countDriverThisMonth,
(SELECT COUNT(*) FROM ride WHERE created_at BETWEEN DATE_FORMAT(CURDATE(), '%Y-%m-01') AND LAST_DAY(CURDATE())) AS countRideThisMonth,
(SELECT COUNT(*) FROM CarRegistration WHERE created_at BETWEEN DATE_FORMAT(CURDATE(), '%Y-%m-01') AND LAST_DAY(CURDATE())) AS countCarRegistrationThisMonth,
-- شكاوى
(SELECT COUNT(*) FROM complaint WHERE date_filed BETWEEN DATE_FORMAT(CURDATE(), '%Y-%m-01') AND LAST_DAY(CURDATE())) AS countComplaintThisMonth,
(SELECT COUNT(*) FROM complaint WHERE date_filed BETWEEN DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY) AND DATE_ADD(DATE_SUB(CURDATE(), INTERVAL WEEKDAY(CURDATE()) DAY), INTERVAL 6 DAY)) AS countComplaintThisWeek,
(SELECT COUNT(*) FROM complaint WHERE DATE(date_filed) = CURDATE()) AS countComplaintToday,
-- المحافظ والتحويلات
-- إحصائيات وقت ومسافة الرحلات
(SELECT TIME_FORMAT(SEC_TO_TIME(AVG(TIMESTAMPDIFF(SECOND, rideTimeStart, rideTimeFinish))), '%Hh %im') FROM ride WHERE rideTimeStart IS NOT NULL AND rideTimeFinish IS NOT NULL) AS driver_avg_duration,
(SELECT MAX(SEC_TO_TIME(TIMESTAMPDIFF(SECOND, rideTimeStart, rideTimeFinish))) FROM ride WHERE rideTimeStart IS NOT NULL AND rideTimeFinish IS NOT NULL) AS longest_duration,
(SELECT ROUND(SUM(distance),2) FROM ride) AS total_distance,
(SELECT ROUND(AVG(distance),2) FROM ride) AS average_distance,
(SELECT ROUND(MAX(distance),2) FROM ride) AS longest_distance,
-- أرباح السائق والشركة
(SELECT SUM(price_for_driver) FROM ride WHERE status = 'Finished') AS total_driver_earnings,
(SELECT ROUND(AVG(price_for_passenger),2) FROM ride) AS avg_passenger_price,
-- توزيع الرحلات حسب الوقت
(SELECT COUNT(*) FROM ride WHERE HOUR(created_at) BETWEEN 6 AND 11) AS morning_ride_count,
(SELECT COUNT(*) FROM ride WHERE HOUR(created_at) BETWEEN 12 AND 17) AS evening_ride_count,
(SELECT COUNT(*) FROM ride WHERE HOUR(created_at) BETWEEN 18 AND 23 OR HOUR(created_at) BETWEEN 0 AND 5) AS night_ride_count,
-- أنواع الرحلات
(SELECT COUNT(*) FROM ride WHERE carType = 'Comfort') AS comfort,
(SELECT COUNT(*) FROM ride WHERE carType = 'Speed') AS speed,
(SELECT COUNT(*) FROM ride WHERE carType = 'Lady') AS lady,
-- حالة الرحلات
(SELECT COUNT(*) FROM ride WHERE status = 'wait') AS ongoing_rides,
(SELECT COUNT(*) FROM ride WHERE status = 'Finished') AS completed_rides,
(SELECT COUNT(*) FROM ride WHERE status = 'cancel') AS cancelled_rides,
-- عدد السائقين الفريدين
(SELECT COUNT(*) FROM (SELECT driver_id FROM ride GROUP BY driver_id) AS sub) AS num_Driver,
-- التحويلات البنكية
(SELECT COUNT(*) FROM payments WHERE payment_method = 'TransferFrom') AS transfer_from_count
FROM passengers
LIMIT 1;
";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
if ($result) {
jsonSuccess($result);
} else {
jsonError("No dashboard data found");
}
?>

41
Admin/driver/deleteCaptain.php Executable file
View File

@@ -0,0 +1,41 @@
<?php
require_once __DIR__ . '/../../connect.php';
$driver_id = filterRequest("driver_id");
$phone = filterRequest("phone");
$reason = filterRequest("reason"); // يمكن أن يأتي من البارامتر أو نخليه افتراضي
if (empty($driver_id) || empty($phone)) {
jsonError("Driver ID and phone are required.");
exit;
}
try {
// تشفير رقم الهاتف
$encPhone = $encryptionHelper->encryptData($phone);
// حذف السائق من جدول driver
$sqlDel = "DELETE FROM driver WHERE id = :id";
$stmtDel = $con->prepare($sqlDel);
$stmtDel->bindParam(':id', $driver_id, PDO::PARAM_INT);
$stmtDel->execute();
if ($stmtDel->rowCount() > 0) {
// إضافة بيانات السائق المحذوف إلى البلاك ليست
$sqlInsert = "INSERT INTO blacklist_driver (driver_id, phone, reason)
VALUES (:driver_id, :phone, :reason)";
$stmtInsert = $con->prepare($sqlInsert);
$stmtInsert->execute([
'driver_id' => $driver_id,
'phone' => $encPhone,
'reason' => !empty($reason) ? $reason : "Deleted & blacklisted by admin"
]);
jsonSuccess(null, "Driver deleted and blacklisted successfully.");
} else {
jsonError("No driver found with the provided ID.");
}
} catch (PDOException $e) {
jsonError("Error: " . $e->getMessage());
}

30
Admin/driver/deleteRecord.php Executable file
View File

@@ -0,0 +1,30 @@
<?php
require_once __DIR__ . '/../../connect.php';
$driver_id = filterRequest("driver_id");
// Prepare the DELETE query
$sql = "DELETE FROM `car_locations` WHERE driver_id = :driver_id";
$stmt = $con->prepare($sql);
// Bind the driver_id parameter
$stmt->bindParam(':driver_id', $driver_id, PDO::PARAM_STR);
try {
// Execute the query
$stmt->execute();
if ($stmt->rowCount() > 0) {
// Success response
jsonSuccess(null, "Record(s) deleted successfully.");
} else {
// Failure response: no records found to delete
jsonError("No records found for the provided driver ID.");
}
} catch (PDOException $e) {
// Handle any SQL errors
jsonError("Error deleting records: " . $e->getMessage());
}
?>

View File

@@ -0,0 +1,55 @@
<?php
require_once __DIR__ . '/../../connect.php';
$phone = filterRequest("phone");
if (empty($phone)) {
jsonError("Phone number is required.");
exit;
}
try {
// تشفير الرقم المدخل للبحث
$encPhone = $encryptionHelper->encryptData($phone);
// احضار كل الأعمدة باستثناء كلمة المرور
$sql = "SELECT *
FROM driver
WHERE phone = :phone
LIMIT 1";
$stmt = $con->prepare($sql);
$stmt->execute([':phone' => $encPhone]);
$driver = $stmt->fetch(PDO::FETCH_ASSOC);
if ($driver) {
// ✅ الحقول المشفرة اللي لازم تنفك:
$encryptedFields = [
'phone',
'email',
'first_name',
'last_name',
'national_number',
'address','gender','site',
'birthdate',
'name_arabic',
];
foreach ($encryptedFields as $field) {
if (!empty($driver[$field])) {
$driver[$field] = $encryptionHelper->decryptData($driver[$field]);
}
}
// ❌ احذف كلمة المرور من النتيجة
unset($driver['password']);
jsonSuccess($driver);
} else {
jsonError("No driver found with this phone.");
}
} catch (PDOException $e) {
jsonError("Error searching driver: " . $e->getMessage());
}

48
Admin/driver/getBestDriver.php Executable file
View File

@@ -0,0 +1,48 @@
<?php
require_once __DIR__ . '/../../connect.php';
$sql = "SELECT
COUNT(`car_locations`.driver_id) AS driver_count,
driver.id,
driver.phone,
driver.name_arabic,
MAX(dt.token) AS token
FROM
`car_locations`
LEFT JOIN driver ON driver.id = car_locations.driver_id
LEFT JOIN driverToken dt ON dt.captain_id = driver.id
WHERE
`car_locations`.created_at > TIMESTAMP(DATE_SUB(NOW(), INTERVAL 7 DAY))
GROUP BY
driver.id
ORDER BY
driver_count DESC
LIMIT 19;
";
$stmt = $con->prepare($sql);
$stmt->execute();
if ($stmt->rowCount() > 0) {
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// فك التشفير للحقول الحساسة
foreach ($rows as &$row) {
if (!empty($row['phone'])) {
$row['phone'] = $encryptionHelper->decryptData($row['phone']);
}
if (!empty($row['name_arabic'])) {
$row['name_arabic'] = $encryptionHelper->decryptData($row['name_arabic']);
}
if (!empty($row['token'])) {
$row['token'] = $encryptionHelper->decryptData($row['token']);
}
}
jsonSuccess($rows);
} else {
jsonError($message = "No recent driver location activity found");
}
?>

View File

@@ -0,0 +1,45 @@
<?php
require_once __DIR__ . '/../../connect.php';
$phone = filterRequest("phone");
// Encrypt phone
$encphone = $encryptionHelper->encryptData($phone);
$sql = "SELECT
*
FROM
`driver`
WHERE
phone = :encPhone";
$stmt = $con->prepare($sql);
// FIX 1: Bind AFTER preparing the statement
// FIX 2: Use the same placeholder name (:encPhone)
$stmt->bindParam(':encPhone', $encphone, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount() > 0) {
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Decrypt sensitive fields
foreach ($rows as &$row) {
if (!empty($row['phone'])) {
$row['phone'] = $encryptionHelper->decryptData($row['phone']);
}
if (!empty($row['name_arabic'])) {
$row['name_arabic'] = $encryptionHelper->decryptData($row['name_arabic']);
}
}
jsonSuccess($rows);
} else {
jsonError("No recent driver location activity found");
}
?>

View File

@@ -0,0 +1,27 @@
<?php
require_once __DIR__ . '/../../connect.php';
$phone = filterRequest("phone");
if (empty($phone)) {
jsonError("Phone number is required.");
exit;
}
try {
// تشفير الرقم للمطابقة مع المخزن
$encPhone = $encryptionHelper->encryptData($phone);
$sql = "DELETE FROM blacklist_driver WHERE phone = :phone";
$stmt = $con->prepare($sql);
$stmt->execute([':phone' => $encPhone]);
if ($stmt->rowCount() > 0) {
jsonSuccess(null, "Driver removed from blacklist successfully.");
} else {
jsonError("No driver found in blacklist with this phone.");
}
} catch (PDOException $e) {
jsonError("Error removing from blacklist: " . $e->getMessage());
}

View File

@@ -0,0 +1,30 @@
<?php
require_once __DIR__ . '/../../connect.php';
$driver_id = filterRequest("id");
$phone = filterRequest("phone");
// تشفير رقم الهاتف
$encphone = $encryptionHelper->encryptData($phone);
$sql = "UPDATE `driver` SET `phone` = :encphone WHERE `id` = :id";
$stmt = $con->prepare($sql);
// Bind values
$stmt->bindParam(':encphone', $encphone, PDO::PARAM_STR);
$stmt->bindParam(':id', $driver_id, PDO::PARAM_STR);
try {
$stmt->execute();
if ($stmt->rowCount() > 0) {
// تم التحديث بنجاح
jsonSuccess(null, "Phone updated successfully.");
} else {
// لم يتم العثور على أي سجل للتحديث
jsonError("No records updated. Please check the driver ID.");
}
} catch (PDOException $e) {
jsonError("Error updating record: " . $e->getMessage());
}
?>

31
Admin/employee/add.php Executable file
View File

@@ -0,0 +1,31 @@
<?php
require_once __DIR__ . '/../../connect.php';
// Get the data from the request
$name = filterRequest("name");
$education = filterRequest("education");
$site = filterRequest("site");
$phone = filterRequest("phone");
$status = filterRequest("status");
$id=filterRequest("id");
// Set the current timestamp for the 'created_at' field
$created_at = date("Y-m-d H:i:s");
// Prepare the SQL insert query using parameterized statements to avoid SQL injection
$sql = "INSERT INTO `employee` (`id`,`name`, `education`, `site`, `phone`, `created_at`, `status`)
VALUES (?,?, ?, ?, ?, ?, ?)";
// Prepare and execute the statement
$stmt = $con->prepare($sql);
$stmt->execute([$id, $name, $education, $site, $phone, $created_at, $status]);
// Check if the query successfully inserted the record
if ($stmt->rowCount() > 0) {
// If a row was inserted, print success
jsonSuccess($message = "Employee record added successfully");
} else {
// If no rows were inserted, print failure
jsonError($message = "Failed to add employee record");
}
?>

29
Admin/employee/get.php Executable file
View File

@@ -0,0 +1,29 @@
<?php
require_once __DIR__ . '/../../connect.php';
// Prepare the SQL query to select all records from the employee table with a limit of 10
$sql = "SELECT
*
FROM
`employee` e
ORDER BY
e.created_at
DESC
";
// Prepare and execute the statement
$stmt = $con->prepare($sql);
$stmt->execute();
// Fetch all records as an associative array
$employee_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Check if any records were retrieved
if ($employee_data) {
// If records were found, print the data as JSON
jsonSuccess($data = $employee_data);
} else {
// If no records were found, print a failure message
jsonError($message = "No employee records found");
}
?>

View File

@@ -0,0 +1,18 @@
<?php
// File: /v1/admin/error/error_list_last20.php
require_once __DIR__ . '/../../connect.php';
try {
$sql = "SELECT `id`, `error`, `userId`, `userType`, `phone`, `created_at`, `device`, `details`, `status`
FROM `error`
ORDER BY `created_at` DESC
LIMIT 20";
$stmt = $con->prepare($sql);
$stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
jsonSuccess($rows);
} catch (Exception $e) {
error_log("error_list_last20.php: " . $e->getMessage());
jsonError($message = "Failed to fetch last 20 errors");
}

View File

@@ -0,0 +1,32 @@
<?php
// File: /v1/admin/error/error_search_by_phone.php
require_once __DIR__ . '/../../connect.php';
try {
$phone = filterRequest("phone");
if ($phone === false || $phone === null || trim($phone) === "") {
jsonError("Phone is required");
exit;
}
// في حال مخزّن الهاتف مشفّر، طبق نفس دالتك للتشفير هنا:
// $enc_phone = $encryptionHelper->encryptData(trim($phone));
// ثم بدّل الحقل في WHERE إلى phone = :ph
$sql = "SELECT `id`, `error`, `userId`, `userType`, `phone`, `created_at`, `device`, `details`, `status`
FROM `error`
WHERE `phone` = :ph OR `phone` LIKE :phLike
ORDER BY `created_at` DESC
LIMIT 20";
$stmt = $con->prepare($sql);
$stmt->execute([
":ph" => trim($phone),
":phLike" => '%' . trim($phone) . '%', // يسمح بجزء من الرقم إن أردت
]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
jsonSuccess($rows);
} catch (Exception $e) {
error_log("error_search_by_phone.php: " . $e->getMessage());
jsonError($message = "Failed to search errors by phone");
}

40
Admin/errorApp.php Executable file
View File

@@ -0,0 +1,40 @@
<?php
require_once __DIR__ . '/../connect.php';
// استلام البيانات من الطلب
$error = filterRequest("error");
$userId = filterRequest("userId");
$userType = filterRequest("userType");
$phone = filterRequest("phone");
$device = filterRequest("device");
$details = filterRequest("details");
// تسجيل الخطأ في ملف logs/app.log للمتابعة السريعة
$logMsg = "[$userType ID: $userId] Error: $error | Where: $device | Details: $details";
appLog($logMsg, "APP_ERROR");
// جملة SQL لإدخال البيانات، مع إضافة الحقل الجديد
// لاحظ أننا لا نرسل حقل 'status' لأنه سيأخذ القيمة الافتراضية 'new' تلقائياً في قاعدة البيانات
$sql = "INSERT INTO `error` (`error`, `userId`, `userType`, `phone`, `device`, `details`)
VALUES (:error, :userId, :userType, :phone, :device, :details)";
$stmt = $con->prepare($sql);
// ربط المتغيرات بالقيم
$stmt->bindParam(':error', $error);
$stmt->bindParam(':userId', $userId);
$stmt->bindParam(':userType', $userType);
$stmt->bindParam(':phone', $phone);
$stmt->bindParam(':device', $device);
$stmt->bindParam(':details', $details); // <-- ربط المتغير الجديد
$stmt->execute();
if ($stmt->rowCount() > 0) {
// طباعة رسالة نجاح مع تفاصيل الخطأ لسهولة التتبع في الكونسول
jsonSuccess($error);
} else {
// طباعة رسالة فشل
jsonError("Failed to save error data");
}
?>

0
Admin/error_log Normal file
View File

37
Admin/facebook.php Executable file
View File

@@ -0,0 +1,37 @@
<?php
require_once 'vendor/autoload.php'; // Include the Composer autoloader
use Facebook\Facebook;
$appId = '$appId'; // Replace with your App ID
$appSecret = '$appSecret'; // Replace with your App Secret
$accessToken = '$accessToken'; // Replace with the token you want to debug
$fb = new Facebook([
'app_id' => $appId,
'app_secret' => $appSecret,
'default_graph_version' => 'v16.0', // Adjust based on your API version
]);
try {
// Generate the app token
$appToken = $appId . '|' . $appSecret;
// Debug the token
$response = $fb->get('/debug_token?input_token=' . $accessToken, $appToken);
$tokenData = $response->getDecodedBody();
// Display the token details
echo "Token Data:\n";
print_r($tokenData);
if (isset($tokenData['data']['expires_at'])) {
echo "Expires At: " . date('Y-m-d H:i:s', $tokenData['data']['expires_at']) . "\n";
} else {
echo "The token does not have an expiration time.\n";
}
} catch (Facebook\Exceptions\FacebookResponseException $e) {
echo 'Graph API Error: ' . $e->getMessage();
} catch (Facebook\Exceptions\FacebookSDKException $e) {
echo 'SDK Error: ' . $e->getMessage();
}

View File

@@ -0,0 +1,100 @@
<?php
require_once __DIR__ . '/../connect.php';
$sql = "SELECT
`passengers`.`id`,
`passengers`.`phone`,
`passengers`.`email`,
`passengers`.`gender`,
`passengers`.`status`,
`passengers`.`birthdate`,
`passengers`.`site`,
`passengers`.`first_name`,
`passengers`.`last_name`,
`passengers`.`sosPhone`,
`passengers`.`education`,
`passengers`.`employmentType`,
`passengers`.`maritalStatus`,
`passengers`.`created_at`,
`passengers`.`updated_at`,
(
SELECT COUNT(`id`) FROM `passengers`
) AS countPassenger,
(
SELECT COUNT(`id`) FROM `feedBack`
) AS countFeedback,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10,2))
FROM `ratingPassenger`
WHERE `passenger_id` = `passengers`.`id`
) AS ratingPassenger,
(
SELECT COUNT(`driverID`)
FROM `ratingPassenger`
WHERE `passenger_id` = `passengers`.`id`
) AS countDriverRate,
(
SELECT COUNT(`passengerID`)
FROM `canecl`
WHERE `passengerID` = `passengers`.`id`
) AS countPassengerCancel,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10,2))
FROM `ratingDriver`
WHERE `passenger_iD` = `passengers`.`id`
) AS passengerAverageRating,
(
SELECT COUNT(`driver_id`)
FROM `ratingDriver`
WHERE `passenger_id` = `passengers`.`id`
) AS countPassengerRate,
(
SELECT COUNT(`ride`.`passenger_id`)
FROM `ride`
WHERE `ride`.`passenger_id` = `passengers`.`id`
) AS countPassengerRide,
(
SELECT `token`
FROM `tokens`
WHERE `tokens`.`passengerID` = `passengers`.`id`
) AS passengerToken
FROM
`passengers`
GROUP BY
`passengers`.`id`
ORDER BY
countPassengerRide DESC
LIMIT 10";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// ✅ فك التشفير للحقول الحساسة
foreach ($result as &$row) {
$fieldsToDecrypt = [
"phone", "email", "gender", "birthdate", "site",
"first_name", "last_name", "sosPhone",
"education", "employmentType", "maritalStatus", "passengerToken"
];
foreach ($fieldsToDecrypt as $field) {
if (isset($row[$field]) && $row[$field] !== null) {
$decrypted = $encryptionHelper->decryptData($row[$field]);
if ($decrypted !== false) {
$row[$field] = $decrypted;
} else {
// سجل أو تجاهل القيم التي فشل فك تشفيرها
$row[$field] = null; // أو احتفظ بالقيمة المشفرة
error_log("Failed to decrypt field '$field' for passenger ID: " . $row['id']);
}
}
}
}
if ($stmt->rowCount() > 0) {
jsonSuccess($data = $result);
} else {
jsonError("No records found");
}
?>

View File

@@ -0,0 +1,96 @@
<?php
require_once __DIR__ . '/../connect.php';
$passengerID = filterRequest("passengerID");
$sql = "SELECT
`passengers`.`id`,
`passengers`.`phone`,
`passengers`.`email`,
`passengers`.`gender`,
`passengers`.`status`,
`passengers`.`birthdate`,
`passengers`.`site`,
`passengers`.`first_name`,
`passengers`.`last_name`,
`passengers`.`sosPhone`,
`passengers`.`education`,
`passengers`.`employmentType`,
`passengers`.`maritalStatus`,
`passengers`.`created_at`,
`passengers`.`updated_at`,
(
SELECT COUNT(`id`) FROM `passengers`
) AS countPassenger,
(
SELECT COUNT(`id`) FROM `feedBack`
) AS countFeedback,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10,2))
FROM `ratingPassenger`
WHERE `passenger_id` = `passengers`.`id`
) AS ratingPassenger,
(
SELECT COUNT(`driverID`)
FROM `ratingPassenger`
WHERE `passenger_id` = `passengers`.`id`
) AS countDriverRate,
(
SELECT COUNT(`passengerID`)
FROM `canecl`
WHERE `passengerID` = `passengers`.`id`
) AS countPassengerCancel,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10,2))
FROM `ratingDriver`
WHERE `passenger_iD` = `passengers`.`id`
) AS passengerAverageRating,
(
SELECT COUNT(`driver_id`)
FROM `ratingDriver`
WHERE `passenger_id` = `passengers`.`id`
) AS countPassengerRate,
(
SELECT COUNT(`ride`.`passenger_id`)
FROM `ride`
WHERE `ride`.`passenger_id` = `passengers`.`id`
) AS countPassengerRide,
(
SELECT `token`
FROM `tokens`
WHERE `tokens`.`passengerID` = `passengers`.`id`
) AS passengerToken
FROM
`passengers`
WHERE
passengers.id = '$passengerID'
GROUP BY
`passengers`.`id`
ORDER BY
countPassengerRide DESC";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// ✅ فك تشفير الحقول الحساسة
foreach ($result as &$row) {
$fieldsToDecrypt = [
"phone", "email", "gender", "birthdate", "site",
"first_name", "last_name", "sosPhone",
"education", "employmentType", "maritalStatus", "passengerToken"
];
foreach ($fieldsToDecrypt as $field) {
if (isset($row[$field]) && $row[$field] !== null) {
$row[$field] = $encryptionHelper->decryptData($row[$field]);
}
}
}
if ($stmt->rowCount() > 0) {
jsonSuccess($result);
} else {
jsonError("No records found");
}
?>

View File

@@ -0,0 +1,91 @@
<?php
require_once __DIR__ . '/../connect.php';
$passengerEmail = $encryptionHelper->encryptData(filterRequest("passengerEmail"));
$passengerId = filterRequest("passengerId");
$passengerphone = $encryptionHelper->encryptData(filterRequest("passengerphone"));
$sql = "SELECT
`passengers`.`id`,
`passengers`.`phone`,
`passengers`.`email`,
`passengers`.`gender`,
`passengers`.`status`,
`passengers`.`birthdate`,
`passengers`.`site`,
`passengers`.`first_name`,
`passengers`.`last_name`,
`passengers`.`sosPhone`,
`passengers`.`education`,
`passengers`.`employmentType`,
`passengers`.`maritalStatus`,
`passengers`.`created_at`,
`passengers`.`updated_at`,
(
SELECT COUNT(`id`) FROM `passengers`
) AS countPassenger,
(
SELECT COUNT(`id`) FROM `feedBack`
) AS countFeedback,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10, 2)) FROM `ratingPassenger`
WHERE `passenger_id` = `passengers`.`id`
) AS ratingPassenger,
(
SELECT COUNT(`driverID`) FROM `ratingPassenger`
WHERE `passenger_id` = `passengers`.`id`
) AS countDriverRate,
(
SELECT COUNT(`passengerID`) FROM `canecl`
WHERE `passengerID` = `passengers`.`id`
) AS countPassengerCancel,
(
SELECT CAST(AVG(`rating`) AS DECIMAL(10, 2)) FROM `ratingDriver`
WHERE `passenger_iD` = `passengers`.`id`
) AS passengerAverageRating,
(
SELECT COUNT(`driver_id`) FROM `ratingDriver`
WHERE `passenger_id` = `passengers`.`id`
) AS countPassengerRate,
(
SELECT COUNT(`passenger_id`) FROM `ride`
WHERE `passenger_id` = `passengers`.`id`
) AS countPassengerRide,
(
SELECT `token` FROM `tokens`
WHERE `passengerID` = `passengers`.`id`
) AS passengerToken
FROM
`passengers`
WHERE
passengers.email = :email OR passengers.phone = :phone OR passengers.id = :id
";
$stmt = $con->prepare($sql);
$stmt->bindParam(":email", $passengerEmail);
$stmt->bindParam(":phone", $passengerphone);
$stmt->bindParam(":id", $passengerId);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// فك التشفير للحقول الحساسة
foreach ($result as &$row) {
$fieldsToDecrypt = [
"phone", "email", "gender", "birthdate", "site",
"first_name", "last_name", "sosPhone",
"education", "employmentType", "maritalStatus"
];
foreach ($fieldsToDecrypt as $field) {
if (isset($row[$field])) {
$row[$field] = $encryptionHelper->decryptData($row[$field]);
}
}
}
if ($stmt->rowCount() > 0) {
jsonSuccess($data = $result);
} else {
jsonError("No records found");
}
?>

View File

@@ -0,0 +1,48 @@
<?php
require_once __DIR__ . '/../connect.php';
// جلب البيانات
$sql = "SELECT
COUNT(DISTINCT driverID) AS driver_count,
`payments`.driverID,
COALESCE(SUM(amount), 0) AS total_amount,
`driver`.`phone`,
`driver`.`name_arabic`,
`driver`.`accountBank`,
`driver`.`bankCode`,
`driver`.`email`
FROM
payments
LEFT JOIN `driver` ON `driver`.`id` = payments.driverID
WHERE
isGiven = 'waiting' AND payment_method IN(
'visa-in', 'visa', 'visaRide', 'TransferFrom',
'payout', 'TransferTo', 'payFromSeferToDriver'
)
AND WEEK(`payments`.created_at) = WEEK(CURRENT_DATE)
GROUP BY
driverID
HAVING
COALESCE(SUM(amount), 0) > 0 AND total_amount > 100
LIMIT 0, 25";
$stmt = $con->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// فك التشفير للحقول المطلوبة
foreach ($result as &$row) {
$fieldsToDecrypt = ['phone', 'email', 'accountBank', 'bankCode', 'name_arabic'];
foreach ($fieldsToDecrypt as $field) {
if (isset($row[$field]) && $row[$field] !== null) {
$row[$field] = $encryptionHelper->decryptData($row[$field]);
}
}
}
if ($stmt->rowCount() > 0) {
jsonSuccess($result);
} else {
jsonError("No wallet record found");
}
?>

53
Admin/ggg.php Normal file
View File

@@ -0,0 +1,53 @@
<?php
// ============================================================
// Admin/ggg.php
// أداة تشفير وفك تشفير للمشرفين
// ============================================================
require_once __DIR__ . '/../core/bootstrap.php';
// نضمن أن الرد دائماً JSON
header('Content-Type: application/json; charset=utf-8');
// 1) قراءة الـ body كـ JSON أو POST
$action = filterRequest('action');
$text = filterRequest('text');
$adminPhoneParam = filterRequest('admin_phone');
// 2) التحقق من رقم هاتف الأدمن المصرّح له
$phonesRaw = getenv('ADMIN_PHONE_NUMBERS') ?: '';
$ALLOWED_TOOL_PHONES = array_values(
array_filter(
array_map(function ($p) {
return preg_replace('/\D+/', '', $p);
}, explode(',', $phonesRaw))
)
);
$adminPhoneParam = $adminPhoneParam ? preg_replace('/\D+/', '', $adminPhoneParam) : '';
if ($adminPhoneParam === '' || !in_array($adminPhoneParam, $ALLOWED_TOOL_PHONES, true)) {
securityLog("Unauthorized encrypt/decrypt attempt", ['phone' => $adminPhoneParam]);
jsonError('Access denied for this admin phone.', 403);
}
if (empty($text) || ($action !== 'encrypt' && $action !== 'decrypt')) {
jsonError('Invalid input: need action=encrypt|decrypt and non-empty text.', 400);
}
// 4) تنفيذ التشفير / الفك (التوافق مع CBC الحالي)
try {
if ($action === 'encrypt') {
$result = $encryptionHelper->encryptData($text);
} else { // decrypt
$result = $encryptionHelper->decryptData($text);
}
jsonSuccess([
'action' => $action,
'result' => (string) $result,
]);
} catch (Exception $e) {
securityLog("Encryption tool failed", ['error' => $e->getMessage()]);
jsonError('Operation failed.', 500);
}

77
Admin/jwtService.php Executable file
View File

@@ -0,0 +1,77 @@
<?php
// ============================================================
// Admin/jwtService.php (Customer Service Login)
// ============================================================
require_once __DIR__ . '/../core/bootstrap.php';
header('Content-Type: application/json');
header("Access-Control-Allow-Origin: https://intaleqapp.com");
header("Access-Control-Allow-Methods: POST, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200);
exit;
}
// ── Rate Limiting ───────────────────────────────────────────
$limiter = new RateLimiter($redis);
$limiter->enforce(RateLimiter::identifier(), 'login');
try {
$email = filterRequest('email') ?? '';
$password = filterRequest('password') ?? '';
$audience = filterRequest('aud') ?? '';
$allowed1 = getenv('allowedService1');
$allowed2 = getenv('allowedService2');
$allowedAudiences = array_values(array_filter([$allowed1, $allowed2]));
if (empty($email) || empty($password) || empty($audience)) {
jsonError('Email and password are required.', 400);
}
if (!in_array($audience, $allowedAudiences, true)) {
jsonError('Invalid audience', 400);
}
$con = Database::get('main');
// استخدام user table ويفضل استخدام password_hash لاحقا مثل admin_users
$stmt = $con->prepare("SELECT `id`, `password`, `email` FROM `users` WHERE email = :email LIMIT 1");
$stmt->execute([':email' => $email]);
$user = $stmt->fetch();
$startTime = microtime(true);
// دعم password_verify مع البقاء على التوافق مع كلمات السر القديمة (Plain Text)
if ($user && (password_verify($password, $user['password']) || $user['password'] === $password)) {
$limiter->reset(RateLimiter::identifier(), 'login');
$jwtService = new JwtService($redis);
$jwt = $jwtService->generateAccessToken($user['id'], 'service', $audience);
$refresh = $jwtService->generateRefreshToken($user['id']);
jsonSuccess([
'jwt' => $jwt,
'refresh_token' => $refresh['token'],
'expires_in' => 900 // أو 6600 كما كان في الكود الأصلي
]);
} else {
$elapsed = microtime(true) - $startTime;
if ($elapsed < 0.1) usleep((int)((0.1 - $elapsed) * 1000000));
securityLog("Service login failed", ['email' => $email]);
jsonError('Invalid email or password', 401);
}
} catch (PDOException $e) {
securityLog("Service Login PDO Error", ['msg' => $e->getMessage()]);
jsonError('Login failed: Database error', 500);
} catch (Exception $e) {
securityLog("Service Login Error", ['msg' => $e->getMessage()]);
jsonError('Login failed: Server error', 500);
}

View File

@@ -0,0 +1,52 @@
<?php
require_once __DIR__ . '/../../connect.php';
function normalize_phone($s) { return preg_replace('/\D+/', '', (string)$s); }
$id = filterRequest("id"); // أو
$phone = filterRequest("phone"); // أحدهما مطلوب
$reason= filterRequest("reason"); // اختياري
$exp = filterRequest("expires_at"); // اختياري Y-m-d H:i:s
if (empty($id) && empty($phone)) { jsonError("Provide id or phone"); exit; }
try {
$con->beginTransaction();
// احضر السجل
if (!empty($id)) {
$sel = $con->prepare("SELECT id, phone FROM passengers WHERE id = :id LIMIT 1");
$sel->execute(['id' => $id]);
} else {
$sel = $con->prepare("SELECT id, phone FROM passengers WHERE phone = :ph LIMIT 1");
$sel->execute(['ph' => $phone]);
}
$p = $sel->fetch(PDO::FETCH_ASSOC);
if (!$p) { throw new Exception("Passenger not found"); }
$phRaw = $p['phone'];
$phNorm= normalize_phone($phRaw);
// أدخِل/حدّث في البلاك ليست
$ins = $con->prepare("
INSERT INTO passenger_blacklist (phone, phone_normalized, reason, expires_at)
VALUES (:ph, :phn, :r, :exp)
ON DUPLICATE KEY UPDATE reason = VALUES(reason), expires_at = VALUES(expires_at)
");
$ins->execute([
'ph' => $phRaw,
'phn' => $phNorm,
'r' => $reason ?: 'Deleted & blacklisted',
'exp' => $exp ?: null
]);
// حذف فعلي
$del = $con->prepare("DELETE FROM passengers WHERE id = :id");
$del->execute(['id' => $p['id']]);
$con->commit();
jsonSuccess(null, "Passenger deleted and blacklisted");
} catch (Throwable $e) {
$con->rollBack();
jsonError("Failed: ".$e->getMessage());
}

View File

@@ -0,0 +1,14 @@
<?php
require_once __DIR__ . '/../../connect.php';
function normalize_phone($s) { return preg_replace('/\D+/', '', (string)$s); }
$phone = filterRequest("phone");
if (empty($phone)) { jsonError("phone is required"); exit; }
$phn = normalize_phone($phone);
$stmt = $con->prepare("DELETE FROM passenger_blacklist WHERE phone_normalized = :phn");
$stmt->execute(['phn' => $phn]);
if ($stmt->rowCount() > 0) { jsonSuccess(null, "Removed from blacklist"); }
else { jsonError("Phone was not blacklisted"); }

View File

@@ -0,0 +1,50 @@
<?php
require_once __DIR__ . '/../../connect.php';
$id = filterRequest("id"); // مفضّل
$first_name = filterRequest("first_name");
$last_name = filterRequest("last_name");
$new_phone = filterRequest("phone");
if (empty($id) ) { jsonError("Provide id or phone_lookup"); exit; }
if ($first_name === null && $last_name === null && $new_phone === null) {
jsonError("Nothing to update"); exit;
}
$sets = [];
$params = [];
$new_phone = $encryptionHelper->encryptData($new_phone);
$first_name = $encryptionHelper->encryptData($first_name);
$last_name = $encryptionHelper->encryptData($last_name);
$enc_norm = $encryptionHelper->encryptData($norm);
if ($first_name !== null) { $sets[] = "first_name = :first_name"; $params['first_name'] = trim($first_name); }
if ($last_name !== null) { $sets[] = "last_name = :last_name"; $params['last_name'] = trim($last_name); }
if ($new_phone !== null) {
$sets[] = "phone = :phone";
$params['phone'] = trim($new_phone);
// منع تكرار الهاتف على راكب آخر
$q = $con->prepare("SELECT id FROM passengers WHERE phone = :ph LIMIT 1");
$q->execute(['ph' => $params['phone']]);
$row = $q->fetch(PDO::FETCH_ASSOC);
if ($row) {
if (!empty($id) && $row['id'] != $id) { jsonError("Phone already used by another passenger"); exit; }
if (empty($id) && $row['id'] != $phoneLookup) { jsonError("Phone already used by another passenger"); exit; }
}
}
$whereSql = "";
$whereParams = [];
if (!empty($id)) { $whereSql = "id = :pid"; $whereParams['pid'] = $id; }
else { $whereSql = "phone = :plk"; $whereParams['plk'] = $phoneLookup; }
$sql = "UPDATE passengers SET ".implode(", ", $sets).", updated_at = CURRENT_TIMESTAMP WHERE $whereSql";
$stmt = $con->prepare($sql);
$ok = $stmt->execute(array_merge($params, $whereParams));
if ($ok && $stmt->rowCount() > 0) { jsonSuccess(null, "Passenger updated"); }
else { jsonError("No change or passenger not found"); }

View File

@@ -0,0 +1,103 @@
<?php
require_once __DIR__ . '/../../connect.php';
$phone = filterRequest('phone');
if (!$phone) {
error_log("[get_last_ride] Missing phone parameter");
jsonError("Phone is required");
exit;
}
$raw = $phone;
// شَفِّر قبل الاستعلام
$enc_raw = $encryptionHelper->encryptData($raw);
try {
error_log("[get_last_ride] Searching passenger with phone=$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);
if (!$passenger) {
error_log("[get_last_ride] Passenger not found (phone=$raw)");
jsonError('Passenger not found for provided phone');
exit;
}
error_log("[get_last_ride] Passenger found id=" . $passenger['id']);
// 2) آخر رحلة لهذا الراكب
$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
FROM ride r
LEFT JOIN driver d ON d.id = r.driver_id
WHERE r.passenger_id = :pid
ORDER BY r.created_at DESC, r.id DESC
LIMIT 1
");
$rideStmt->execute(['pid' => $passenger['id']]);
$ride = $rideStmt->fetch(PDO::FETCH_ASSOC);
if (!$ride) {
error_log("[get_last_ride] No rides found for passenger_id=" . $passenger['id']);
jsonError('No rides found for this passenger');
exit;
}
error_log("[get_last_ride] Found ride id=" . $ride['id'] . " for passenger_id=" . $passenger['id']);
// فك التشفير
$passenger['first_name'] = $encryptionHelper->decryptData($passenger['first_name']);
$passenger['last_name'] = $encryptionHelper->decryptData($passenger['last_name']);
$passenger['phone'] = $encryptionHelper->decryptData($passenger['phone']);
$ride['driver_first_name'] = $encryptionHelper->decryptData($ride['driver_first_name']);
$ride['driver_last_name'] = $encryptionHelper->decryptData($ride['driver_last_name']);
// 3) اطبع النتيجة
$response = [
'passenger' => [
'id' => $passenger['id'],
'first_name' => $passenger['first_name'],
'last_name' => $passenger['last_name'],
'phone' => $passenger['phone'],
],
'ride' => $ride
];
error_log("[get_last_ride] Success response for passenger_id=" . $passenger['id']);
jsonSuccess($response);
} catch (Throwable $e) {
error_log("[get_last_ride] Exception: " . $e->getMessage());
jsonError("Error: " . $e->getMessage());
}

View File

@@ -0,0 +1,87 @@
<?php
require_once __DIR__ . '/../../connect.php';
$rideId = filterRequest('id');
$status = filterRequest('status');
$reason = filterRequest('reason'); // اختياري
if (empty($rideId) || empty($status)) {
jsonError("id and status are required");
exit;
}
/* whitelist للحالات المسموحة عدّل حسب نظامك */
$allowed = [
'Pending', 'Accepted', 'EnRoute', 'Arrived',
'Started', 'Completed', 'Canceled'
];
if (!in_array($status, $allowed, true)) {
jsonError("Invalid status");
exit;
}
try {
$con->beginTransaction();
// إن أردت ختم وقت النهاية تلقائيًا عند الإكمال
if ($status === 'Completed') {
$sql = "UPDATE ride
SET status = :st, rideTimeFinish = IFNULL(rideTimeFinish, NOW()), updated_at = CURRENT_TIMESTAMP
WHERE id = :id";
} else {
$sql = "UPDATE ride
SET status = :st, updated_at = CURRENT_TIMESTAMP
WHERE id = :id";
}
$stmt = $con->prepare($sql);
$ok = $stmt->execute(['st' => $status, 'id' => $rideId]);
if (!$ok || $stmt->rowCount() === 0) {
$con->rollBack();
jsonError("Ride not found or no change");
exit;
}
// أعِدّ بيانات الرحلة المحدّثة (للتحديث الفوري في الواجهة)
$fetch = $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
FROM ride r
LEFT JOIN driver d ON d.id = r.driver_id
WHERE r.id = :id
LIMIT 1
");
$fetch->execute(['id' => $rideId]);
$ride = $fetch->fetch(PDO::FETCH_ASSOC);
$con->commit();
jsonSuccess(['ride' => $ride, 'message' => 'Status updated']);
} catch (Throwable $e) {
if ($con->inTransaction()) $con->rollBack();
jsonError("Error: ".$e->getMessage());
}

View File

@@ -0,0 +1,50 @@
<?php
// =================================================================
// ملف: get_driver_live_pos.php
// الوظيفة: جلب الموقع اللحظي لسائق محدد (بناءً على ID)
// =================================================================
require_once __DIR__ . '/../../connect.php'; // تأكد أن هذا الملف يحتوي على $con_tracking
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
try {
// 1. استقبال معرف السائق
$driver_id = filterRequest("driver_id");
if (!$driver_id) {
jsonError("driver_id is required");
exit;
}
// 2. الاستعلام من قاعدة بيانات التتبع (car_locations)
// نجلب أحدث إحداثيات تم تسجيلها لهذا السائق
$sql = "
SELECT
latitude,
longitude,
heading,
speed,
updated_at
FROM car_locations
WHERE driver_id = ?
ORDER BY updated_at DESC
LIMIT 1
";
$stmt = $con_tracking->prepare($sql);
$stmt->execute([$driver_id]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if ($data) {
jsonSuccess($data);
} else {
// السائق ليس له موقع مسجل (ربما لم يشغل التطبيق بعد)
jsonError("No location found for this driver");
}
} catch (PDOException $e) {
jsonError("Database Error: " . $e->getMessage());
}
?>

View File

@@ -0,0 +1,108 @@
<?php
require_once __DIR__ . '/../../connect.php';
header("Access-Control-Allow-Origin: *");
header('Content-Type: application/json; charset=utf-8');
try {
$statusFilter = filterRequest("status");
// القيم المتوقعة من التطبيق: 'All', 'Begin', 'New', 'Completed', 'Canceled'
if (!$statusFilter) $statusFilter = "Begin";
$params = [];
$whereClause = "";
// --- منطق ترجمة الحالات (Mapping Logic) ---
switch ($statusFilter) {
case 'All':
$whereClause = ""; // لا يوجد شرط، اجلب الكل
break;
case 'Begin':
// قد تكون الرحلة بدأت أو وصل السائق
$whereClause = "WHERE r.status IN ('Begin','Apply','Applied')";
break;
case 'New':
$whereClause = "WHERE r.status = 'New'";
break;
case 'Completed':
// في قاعدة البيانات الحالة اسمها Finished
$whereClause = "WHERE r.status = 'Finished'";
break;
case 'Canceled':
// نجمع كل حالات الإلغاء الممكنة
$whereClause = "WHERE r.status IN ('Cancel', 'CancelFromDriverAfterApply', 'TimeOut')";
break;
default:
// في حال تم إرسال حالة محددة غير المذكورين
$whereClause = "WHERE r.status = ?";
$params[] = $statusFilter;
break;
}
// --- الاستعلام ---
$sql = "
SELECT
r.*,
-- بيانات السائق
d.first_name as d_fname, d.last_name as d_lname, d.phone as d_phone, d.id as driver_real_id,
-- إحصائيات السائق (نحسب المكتمل والملغي بشكل أدق)
(SELECT COUNT(*) FROM ride WHERE driver_id = d.id AND status = 'Finished') as d_completed,
(SELECT COUNT(*) FROM ride WHERE driver_id = d.id AND status LIKE 'Cancel%') as d_canceled,
-- بيانات الراكب
p.first_name as p_fname, p.last_name as p_lname, p.phone as p_phone,
-- إحصائيات الراكب
(SELECT COUNT(*) FROM ride WHERE passenger_id = p.id AND status = 'Finished') as p_completed,
-- سبب الإلغاء
-- نحاول جلبه من جدول driver_orders (ملاحظات السائق)
-- نستخدم COALESCE لجلب 'لا يوجد سبب' إذا كانت القيمة فارغة
COALESCE(
(SELECT notes FROM driver_orders WHERE order_id = r.id LIMIT 1),
'لا يوجد سبب مسجل'
) as cancel_reason
FROM ride r
LEFT JOIN driver d ON r.driver_id = d.id
LEFT JOIN passengers p ON r.passenger_id = p.id
$whereClause
ORDER BY r.id DESC
LIMIT 100
";
$stmt = $con->prepare($sql);
$stmt->execute($params);
$rides = $stmt->fetchAll(PDO::FETCH_ASSOC);
$data = [];
foreach ($rides as $row) {
// فك التشفير
try { $row['d_fname'] = $encryptionHelper->decryptData($row['d_fname']); } catch(Exception $e){}
try { $row['d_lname'] = $encryptionHelper->decryptData($row['d_lname']); } catch(Exception $e){}
try { $row['d_phone'] = $encryptionHelper->decryptData($row['d_phone']); } catch(Exception $e){}
try { $row['p_fname'] = $encryptionHelper->decryptData($row['p_fname']); } catch(Exception $e){}
try { $row['p_lname'] = $encryptionHelper->decryptData($row['p_lname']); } catch(Exception $e){}
try { $row['p_phone'] = $encryptionHelper->decryptData($row['p_phone']); } catch(Exception $e){}
$row['driver_full_name'] = trim($row['d_fname'] . ' ' . $row['d_lname']);
$row['passenger_full_name'] = trim($row['p_fname'] . ' ' . $row['p_lname']);
if(empty($row['driver_full_name'])) $row['driver_full_name'] = "Unknown Driver";
if(empty($row['passenger_full_name'])) $row['passenger_full_name'] = "Unknown Passenger";
$data[] = $row;
}
jsonSuccess($data);
} catch (PDOException $e) {
jsonError("Database Error: " . $e->getMessage());
}
?>

150
Admin/rides/monitorRide.php Executable file
View File

@@ -0,0 +1,150 @@
<?php
require_once __DIR__ . '/../../connect.php';
// 1. Log the start of the request
$phone = filterRequest("phone");
error_log("[MONITOR_RIDE] ---------------- START REQUEST ----------------");
error_log("[MONITOR_RIDE] 1. Received Phone: " . $phone);
//------------------------------------------------------------------------
// 1) البحث عن الهاتف أولاً في جدول السائق ثم جدول الراكب
//------------------------------------------------------------------------
$encPhone = $encryptionHelper->encryptData($phone);
error_log("[MONITOR_RIDE] 2. Encrypted Phone: " . $encPhone);
// Check Driver Table
$driverQuery = $con->prepare("SELECT id AS driverID FROM driver WHERE phone = :phone LIMIT 1");
$driverQuery->execute([':phone' => $encPhone]);
$driver = $driverQuery->fetch(PDO::FETCH_ASSOC);
// Check Passenger Table
$customerQuery = $con->prepare("SELECT id AS customerID FROM passengers WHERE phone = :phone LIMIT 1");
$customerQuery->execute([':phone' => $encPhone]);
$customer = $customerQuery->fetch(PDO::FETCH_ASSOC);
// حدد نوع المستخدم
$userType = '';
$driverID = null;
$customerID = null;
if ($driver) {
$userType = 'driver';
$driverID = $driver['driverID'];
error_log("[MONITOR_RIDE] 3. User Found: Type = DRIVER, ID = " . $driverID);
} elseif ($customer) {
$userType = 'customer';
$customerID = $customer['customerID'];
error_log("[MONITOR_RIDE] 3. User Found: Type = CUSTOMER, ID = " . $customerID);
} else {
error_log("[MONITOR_RIDE] 3. FAILURE: Phone number not found in Driver or Passenger tables.");
jsonError("رقم الهاتف غير موجود في النظام.");
exit;
}
//------------------------------------------------------------------------
// 2) جلب آخر رحلة حالتها "بدأت" بناءً على نوع المستخدم
//------------------------------------------------------------------------
if ($userType == 'driver') {
error_log("[MONITOR_RIDE] 4. Searching for active ride for Driver ID: " . $driverID);
$rideQuery = $con->prepare("
SELECT * FROM ride
WHERE driver_id = :driverID AND status = 'Begin'
ORDER BY id DESC LIMIT 1
");
$rideQuery->execute([':driverID' => $driverID]);
} else {
error_log("[MONITOR_RIDE] 4. Searching for active ride for Customer ID: " . $customerID);
$rideQuery = $con->prepare("
SELECT * FROM ride
WHERE passenger_id = :customerID AND status = 'Begin'
ORDER BY id DESC LIMIT 1
");
$rideQuery->execute([':customerID' => $customerID]);
}
$ride = $rideQuery->fetch(PDO::FETCH_ASSOC);
if (!$ride) {
error_log("[MONITOR_RIDE] 4. FAILURE: No ride with status 'Begin' found.");
jsonError("لا توجد رحلة بدأت لهذا المستخدم.");
exit;
} else {
error_log("[MONITOR_RIDE] 4. SUCCESS: Active Ride Found. Ride ID: " . $ride['id']);
}
//------------------------------------------------------------------------
// 3) جلب معلومات السائق من الرحلة
//------------------------------------------------------------------------
// FIX 1: Safe assignment of driver ID (checking driverID vs driver_id)
$rideDriverID = $ride['driverID'] ?? $ride['driver_id'];
error_log("[MONITOR_RIDE] 5. Fetching info for Driver ID from Ride: " . $rideDriverID);
// FIX 2: Select first_name and last_name instead of fullname
$driverInfoQuery = $con->prepare("
SELECT id, first_name, last_name, phone
FROM driver
WHERE id = :driverID
LIMIT 1
");
$driverInfoQuery->execute([':driverID' => $rideDriverID]);
$driverInfo = $driverInfoQuery->fetch(PDO::FETCH_ASSOC);
if ($driverInfo) {
// فك التشفير للهاتف
$driverInfo['phone'] = $encryptionHelper->decryptData($driverInfo['phone']);
// FIX 4: Decrypt First Name and Last Name
$driverInfo['first_name'] = $encryptionHelper->decryptData($driverInfo['first_name']);
$driverInfo['last_name'] = $encryptionHelper->decryptData($driverInfo['last_name']);
// Construct fullname for the response
$fullName = $driverInfo['first_name'] . " " . $driverInfo['last_name'];
$driverInfo['fullname'] = $fullName;
error_log("[MONITOR_RIDE] 5. Driver Info Found: " . $fullName);
} else {
error_log("[MONITOR_RIDE] 5. WARNING: Driver info not found for ID " . $rideDriverID);
}
//------------------------------------------------------------------------
// 4) جلب آخر موقع للسائق من جدول driver_location بشرط الحالة ON
//------------------------------------------------------------------------
error_log("[MONITOR_RIDE] 6. Querying Tracking DB for Driver ID: " . $rideDriverID);
// FIX 3: Changed ORDER BY id DESC to ORDER BY updated_at DESC
$locationQuery = $con_tracking->prepare("
SELECT latitude, longitude, speed, heading, updated_at
FROM car_locations
WHERE driver_id = :driverID AND status = 'ON'
ORDER BY updated_at DESC LIMIT 1
");
$locationQuery->execute([':driverID' => $rideDriverID]);
$location = $locationQuery->fetch(PDO::FETCH_ASSOC);
if ($location) {
error_log("[MONITOR_RIDE] 6. Location Found: Lat=" . $location['latitude'] . " Lng=" . $location['longitude'] . " Updated=" . $location['updated_at']);
} else {
error_log("[MONITOR_RIDE] 6. WARNING: No live location found (status=ON) or list empty.");
}
//------------------------------------------------------------------------
// 5) تجهيز البيانات للرد
//------------------------------------------------------------------------
$response = [
"ride_details" => $ride,
"driver_details" => $driverInfo,
"driver_location" => $location ?: "No live location"
];
error_log("[MONITOR_RIDE] 7. Sending Success Response.");
jsonSuccess($response);
?>

View File

@@ -0,0 +1,87 @@
<?php
// File: send_payment_received_email.php
require_once __DIR__ . '/../connect.php';
$driverID = filterRequest('driverID');
$totalAmount = filterRequest('total_amount');
$driverPhone = filterRequest('phone');
$driverArabicName = filterRequest('name_arabic');
$accountBank = filterRequest('accountBank');
$driverEmail = filterRequest('email');
// لغة الإيميل (تلقائي إنجليزي حالياً، يمكن تعيينها لاحقًا حسب المستخدم)
$language = 'en';
// عنوان واسم التطبيق الرسمي
$appName = "tripz"; // الاسم الجديد مع حرف "Z"
$domain = "https://tripz-egypt.com";
// محتوى الإيميل - باللغة الإنجليزية
$bodyEmail = "<html>
<head>
<style>
body { font-family: Arial, sans-serif; color: #333; background: #f9f9f9; padding: 20px; }
.container { background: #fff; padding: 30px; border-radius: 8px; max-width: 600px; margin: auto; }
h1 { color: #007bff; }
p { font-size: 16px; }
</style>
</head>
<body>
<div class='container'>
<img src='$domain/assets/logo.png' alt='$appName Logo' style='width: 150px; margin: 20px auto; display: block;'>
<h1>Payment Sent - $appName</h1>
<p>Thank you for being a valued driver on the $appName platform.</p>
<p>We have sent a payment of <strong>$totalAmount EGP</strong> to your account <strong>$accountBank</strong>.</p>
<p>Please note that it may take a few days for your bank to process this transaction.</p>
<p>We appreciate your efforts and are proud to have you on board with $appName.</p>
<p style='margin-top: 40px;'>Regards,<br><strong>tripz Team</strong></p>
<p style='font-size: 12px; color: #888;'>tripz, Egypt | $domain</p>
</div>
</body>
</html>";
// محتوى الإيميل - باللغة العربية
$bodyEmailAr = "<html>
<head>
<style>
body { font-family: 'Cairo', sans-serif; color: #333; background: #f9f9f9; padding: 20px; direction: rtl; }
.container { background: #fff; padding: 30px; border-radius: 8px; max-width: 600px; margin: auto; text-align: right; }
h1 { color: #007bff; }
p { font-size: 16px; }
</style>
</head>
<body>
<div class='container'>
<img src='$domain/assets/logo.png' alt='$appName' style='width: 150px; margin: 20px auto; display: block;'>
<h1>تم إرسال الدفعة - $appName</h1>
<p>شكرًا لك لكونك سائقًا مميزًا على منصة $appName.</p>
<p>لقد تم إرسال دفعة قدرها <strong>$totalAmount جنيه</strong> إلى حسابك <strong>$accountBank</strong>.</p>
<p>يرجى ملاحظة أن عملية التحويل قد تستغرق بضعة أيام حسب إجراءات البنك.</p>
<p>نقدّر جهودك ونتطلع إلى استمرار الشراكة معك على تطبيق $appName.</p>
<p style='margin-top: 40px;'>مع التحية،<br><strong>فريق $appName</strong></p>
<p style='font-size: 12px; color: #888;'>$appName - مصر | $domain</p>
</div>
</body>
</html>";
// إعدادات الإيميل
$supportEmail = 'support@tripz-egypt.com';
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
$headers .= "From: tripz Egypt <$supportEmail>\r\n";
// إرسال الإيميل إن وُجد عنوان صالح
if (!empty($driverEmail)) {
$subject = "Payment Sent - $appName";
$message = ($language === 'ar') ? $bodyEmailAr : $bodyEmail;
if (mail($driverEmail, $subject, $message, $headers)) {
jsonSuccess(null, "Email sent successfully to $driverEmail");
} else {
jsonError("Failed to send email to $driverEmail");
}
} else {
jsonError("Invalid or missing driver email address.");
}
?>

79
Admin/send_whatsapp_message.php Executable file
View File

@@ -0,0 +1,79 @@
<?php
// File: send_whatsapp_message.php
// هذا السكربت يرسل رسالة واتساب فقط باستخدام RaseelPlus API
require_once __DIR__ . '/../connect.php'; // فقط إذا كنت تحتاج للوصول إلى environment
error_log("--- [send_whatsapp_message.php] Script execution started ---");
// استقبال المعطيات من POST
$receiver = filterRequest("receiver"); // رقم الهاتف
$message = filterRequest("message"); // نص الرسالة
if (empty($receiver) || empty($message)) {
error_log("[send_whatsapp_message.php] Error: Missing receiver or message.");
jsonError('Phone number and message are required.');
exit();
}
// بيانات Raseel
$instanceId = getenv("RASEEL_DRIVER_INSTANCE_ID");
$accessToken = getenv("RASEEL_DRIVER_ACCESS_TOKEN");
// API URL
$apiUrl = 'https://raseelplus.com/api/send';
// تجهيز البيانات للإرسال
$payload = [
"number" => $receiver,
"type" => "text",
"message" => $message,
"instance_id" => $instanceId,
"access_token"=> $accessToken
];
error_log("[send_whatsapp_message.php] Sending payload: " . json_encode($payload));
// إرسال الطلب
$response = callAPI("POST", $apiUrl, json_encode($payload));
error_log("[send_whatsapp_message.php] Raw response: " . print_r($response, true));
// فحص الاستجابة
if ($response && !isset($response->error) && (isset($response->status) && $response->status == 'success' || isset($response->message))) {
jsonSuccess(null, "Message sent successfully.");
} else {
$errorMessage = isset($response->message) ? $response->message : "Unknown error.";
error_log("[send_whatsapp_message.php] Failed to send: $errorMessage");
jsonError("Failed to send message: $errorMessage");
}
// دالة cURL
function callAPI($method, $url, $data)
{
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Accept: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
error_log("[callAPI] cURL Error: $err");
return null;
} else {
return json_decode($response);
}
}
?>

31
Admin/view_errors.php Executable file
View File

@@ -0,0 +1,31 @@
<?php
require_once __DIR__ . '/../connect.php';
// استلام 'status' كمتغير اختياري لتصفية النتائج
// مثلاً: view_errors.php?status=new سيجلب الأخطاء الجديدة فقط
$status = filterRequest("status");
// إذا تم تحديد status، قم بتصفية النتائج بناءً عليه
if (!empty($status)) {
$stmt = $con->prepare("SELECT * FROM `error` WHERE `status` = ? ORDER BY `created_at` DESC");
$stmt->execute(array($status));
} else {
// إذا لم يتم تحديد status، قم بجلب جميع الأخطاء
$stmt = $con->prepare("SELECT * FROM `error` ORDER BY `created_at` DESC");
$stmt->execute();
}
// جلب جميع النتائج
$errors = $stmt->fetchAll(PDO::FETCH_ASSOC);
$count = $stmt->rowCount();
if ($count > 0) {
// إرجاع البيانات كـ JSON مع رسالة نجاح
echo json_encode(array("status" => "success", "data" => $errors));
} else {
// في حال عدم وجود أخطاء، إرجاع رسالة نجاح مع بيانات فارغة
echo json_encode(array("status" => "success", "data" => []));
}
?>