getConnection() */ function openDatabaseConnection() { return DatabaseService::getInstance()->getConnection(); } // ============================================================================= // EMAIL FUNCTIONS - Delegates to EmailService // ============================================================================= function sendVerificationEmail($email, $name, $token) { $service = new EmailService(); return $service->sendVerificationEmail($email, $name, $token); } function sendInvoice($email, $name, $eft_id, $amount, $description) { $service = new EmailService(); return $service->sendInvoice($email, $name, $eft_id, $amount, $description); } function sendPOP($fullname, $eft_id, $amount, $description) { $service = new EmailService(); $adminEmail = $_ENV['ADMIN_EMAIL'] ?? 'admin@4wdcsa.co.za'; $htmlContent = "

POP received for {$fullname}.
EFT ID: {$eft_id}
Amount: R{$amount}

"; return $service->sendCustom($adminEmail, 'Administrator', '4WDCSA - Proof of Payment Received', $htmlContent); } function sendEmail($email, $name, $subject, $htmlContent) { $service = new EmailService(); return $service->sendCustom($email, $name, $subject, $htmlContent); } function sendAdminNotification($subject, $message) { $service = new EmailService(); return $service->sendAdminNotification($subject, $message); } function sendPaymentConfirmation($email, $name, $payment_id, $amount, $description) { $service = new EmailService(); return $service->sendPaymentConfirmation($email, $name, $payment_id, $amount, $description); } // ============================================================================= // PAYMENT FUNCTIONS - Delegates to PaymentService // ============================================================================= function processPayment($payment_id, $amount, $description) { $service = new PaymentService(); $userService = new UserService(); $user_id = $_SESSION['user_id'] ?? 0; $userInfo = [ 'user_id' => $user_id, 'first_name' => $userService->getFirstName($user_id), 'last_name' => $userService->getLastName($user_id), 'email' => $userService->getEmail($user_id) ]; $domain = $_ENV['PAYFAST_DOMAIN'] ?? 'www.thepinto.co.za/4wdcsa'; $encryptedId = base64_encode($payment_id); $html = $service->processBookingPayment( $payment_id, $amount, $description, 'https://' . $domain . '/bookings.php', 'https://' . $domain . '/cancel_booking.php?booking_id=' . $encryptedId, 'https://' . $domain . '/confirm.php', $userInfo ); echo $html; ob_end_flush(); } function processMembershipPayment($payment_id, $amount, $description) { $service = new PaymentService(); $userService = new UserService(); $user_id = $_SESSION['user_id'] ?? 0; $userInfo = [ 'user_id' => $user_id, 'first_name' => $userService->getFirstName($user_id), 'last_name' => $userService->getLastName($user_id), 'email' => $userService->getEmail($user_id) ]; $html = $service->processMembershipPayment($payment_id, $amount, $description, $userInfo); echo $html; ob_end_flush(); } function processPaymentTest($payment_id, $amount, $description) { $service = new PaymentService(); $user_id = $_SESSION['user_id'] ?? 0; if ($service->processTestPayment($payment_id, $amount, $description, $user_id)) { header("Location: bookings.php"); exit(); } else { echo json_encode(['status' => 'error', 'message' => 'Payment processing failed']); exit(); } } function processZeroPayment($payment_id, $description) { $service = new PaymentService(); $user_id = $_SESSION['user_id'] ?? 0; if ($service->processZeroPayment($payment_id, $description, $user_id)) { header("Location: bookings.php"); exit(); } else { echo json_encode(['status' => 'error', 'message' => 'Payment processing failed']); exit(); } } // ============================================================================= // AUTHENTICATION FUNCTIONS - Delegates to AuthenticationService // ============================================================================= function checkAdmin() { $service = new AuthenticationService(); return $service->requireAdmin(); } function checkSuperAdmin() { $service = new AuthenticationService(); return $service->requireSuperAdmin(); } // ============================================================================= // USER INFORMATION FUNCTIONS - Delegates to UserService // ============================================================================= function getFullName($user_id) { $service = new UserService(); return $service->getFullName((int)$user_id); } function getFirstName($user_id) { $service = new UserService(); return $service->getFirstName((int)$user_id); } function getEmail($user_id) { $service = new UserService(); return $service->getEmail((int)$user_id); } function getProfilePic($user_id) { $service = new UserService(); return $service->getProfilePic((int)$user_id); } function getLastName($user_id) { $service = new UserService(); return $service->getLastName((int)$user_id); } function getInitialSurname($user_id) { $service = new UserService(); return $service->getInitialSurname((int)$user_id); } function get_user_info($info) { $user_id = $_SESSION['user_id'] ?? 0; $service = new UserService(); $data = $service->getUserInfo((int)$user_id, [$info]); return $data[$info] ?? null; } // ============================================================================= // UTILITY FUNCTIONS - Date/Time and Formatting // ============================================================================= function convertDate($dateString) { try { $date = DateTime::createFromFormat('Y-m-d', $dateString); if ($date) { return $date->format('D, d M Y'); } } catch (Exception $e) { error_log("convertDate error: " . $e->getMessage()); } return "Invalid date format"; } function calculateDaysAndNights($startDate, $endDate) { try { $start = DateTime::createFromFormat('Y-m-d', $startDate); $end = DateTime::createFromFormat('Y-m-d', $endDate); if ($start && $end) { $interval = $start->diff($end); $days = $interval->days + 1; $nights = $days - 1; return "$days days $nights nights"; } } catch (Exception $e) { error_log("calculateDaysAndNights error: " . $e->getMessage()); } return "Invalid date format"; } function getEFTDetails($eft_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT amount, description FROM efts WHERE eft_id = ? LIMIT 1"); if (!$stmt) { error_log("getEFTDetails prepare error: " . $conn->error); return false; } $stmt->bind_param("s", $eft_id); $stmt->execute(); $result = $stmt->get_result(); $stmt->close(); return $result->fetch_assoc() ?: false; } // ============================================================================= // MEMBERSHIP & STATUS FUNCTIONS // ============================================================================= function getUserMemberStatus($user_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare(" SELECT COUNT(*) as total FROM membership_application WHERE user_id = ? AND payment_status = 'PAID' AND accept_indemnity = 1 LIMIT 1 "); if (!$stmt) { error_log("getUserMemberStatus prepare error: " . $conn->error); return false; } $stmt->bind_param("i", $user_id); $stmt->execute(); $stmt->bind_result($count); $stmt->fetch(); $stmt->close(); return $count > 0; } function getUserMemberStatusPending($user_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare(" SELECT COUNT(*) as total FROM membership_application WHERE user_id = ? AND (payment_status = 'AWAITING PAYMENT' OR payment_status = 'PENDING') LIMIT 1 "); if (!$stmt) { error_log("getUserMemberStatusPending prepare error: " . $conn->error); return false; } $stmt->bind_param("i", $user_id); $stmt->execute(); $stmt->bind_result($count); $stmt->fetch(); $stmt->close(); return $count > 0; } function checkMembershipApplication($user_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT COUNT(*) as total FROM membership_application WHERE user_id = ? LIMIT 1"); if (!$stmt) { return false; } $stmt->bind_param("i", $user_id); $stmt->execute(); $stmt->bind_result($count); $stmt->fetch(); $stmt->close(); return $count > 0; } function checkMembershipApplication2($user_id) { return checkMembershipApplication($user_id); } // ============================================================================= // ROLE & AUTHORIZATION FUNCTIONS // ============================================================================= function getUserRole($user_id = null) { if ($user_id === null) { $user_id = $_SESSION['user_id'] ?? 0; } if (!$user_id) { return null; } $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT role FROM users WHERE user_id = ? LIMIT 1"); if (!$stmt) { return null; } $stmt->bind_param("i", $user_id); $stmt->execute(); $stmt->bind_result($role); $stmt->fetch(); $stmt->close(); return $role; } // ============================================================================= // TRIP & BOOKING FUNCTIONS // ============================================================================= function getTripCount() { $conn = openDatabaseConnection(); $result = $conn->query("SELECT COUNT(*) AS total FROM trips WHERE published = 1 AND start_date > CURDATE()"); if ($result && $result->num_rows > 0) { $row = $result->fetch_assoc(); return (int)$row['total']; } return 0; } function countUpcomingTrips() { return getTripCount(); } function getAvailableSpaces($trip_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT vehicle_capacity FROM trips WHERE trip_id = ? LIMIT 1"); if (!$stmt) { return 0; } $stmt->bind_param("i", $trip_id); $stmt->execute(); $stmt->bind_result($capacity); $stmt->fetch(); $stmt->close(); if ($capacity === null) { return 0; } $stmt2 = $conn->prepare("SELECT COUNT(*) as booked FROM bookings WHERE trip_id = ? AND status = 'PAID'"); $stmt2->bind_param("i", $trip_id); $stmt2->execute(); $stmt2->bind_result($booked); $stmt2->fetch(); $stmt2->close(); return max(0, $capacity - ($booked ?? 0)); } function countUpcomingBookings($user_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare(" SELECT COUNT(*) as total FROM bookings WHERE user_id = ? AND trip_id IN ( SELECT trip_id FROM trips WHERE start_date > NOW() ) "); if (!$stmt) { return 0; } $stmt->bind_param("i", $user_id); $stmt->execute(); $stmt->bind_result($count); $stmt->fetch(); $stmt->close(); return (int)($count ?? 0); } // ============================================================================= // EFT & PAYMENT RECORDING // ============================================================================= function addEFT($eft_id, $user_id, $payment_status, $eftamount, $description) { $conn = openDatabaseConnection(); $stmt = $conn->prepare(" INSERT INTO efts (eft_id, user_id, payment_status, amount, description) VALUES (?, ?, ?, ?, ?) "); if (!$stmt) { error_log("addEFT prepare error: " . $conn->error); return false; } $stmt->bind_param("sisds", $eft_id, $user_id, $payment_status, $eftamount, $description); $result = $stmt->execute(); $stmt->close(); return $result; } function addSubsEFT($eft_id, $user_id, $payment_status, $eftamount, $description) { return addEFT($eft_id, $user_id, $payment_status, $eftamount, $description); } function getUserIdFromEFT($eft_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT user_id FROM efts WHERE eft_id = ? LIMIT 1"); if (!$stmt) { return null; } $stmt->bind_param("s", $eft_id); $stmt->execute(); $stmt->bind_result($user_id); $stmt->fetch(); $stmt->close(); return $user_id; } function getEftDescription($eft_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT description FROM efts WHERE eft_id = ? LIMIT 1"); if (!$stmt) { return null; } $stmt->bind_param("s", $eft_id); $stmt->execute(); $stmt->bind_result($description); $stmt->fetch(); $stmt->close(); return $description; } // ============================================================================= // VISITOR & SECURITY FUNCTIONS // ============================================================================= function logVisitor() { try { $ip = getUserIP(); $country = guessCountry(); $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown'; $conn = openDatabaseConnection(); $stmt = $conn->prepare("INSERT INTO visitors (ip_address, country, user_agent) VALUES (?, ?, ?)"); if ($stmt) { $stmt->bind_param("sss", $ip, $country, $user_agent); $stmt->execute(); $stmt->close(); } } catch (Exception $e) { error_log("logVisitor error: " . $e->getMessage()); } } function getUserIP() { if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) { return $_SERVER['HTTP_CF_CONNECTING_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { return explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0]; } elseif (!empty($_SERVER['REMOTE_ADDR'])) { return $_SERVER['REMOTE_ADDR']; } return 'UNKNOWN'; } function guessCountry() { $ip = getUserIP(); if ($ip === 'UNKNOWN') { return 'UNKNOWN'; } try { $response = file_get_contents("http://ip-api.com/json/{$ip}?fields=country"); if ($response) { $data = json_decode($response, true); return $data['country'] ?? 'UNKNOWN'; } } catch (Exception $e) { error_log("guessCountry error: " . $e->getMessage()); } return 'UNKNOWN'; } function blockBlacklistedIP() { $ip = getUserIP(); $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT 1 FROM blacklist WHERE ip_address = ? LIMIT 1"); if (!$stmt) { return; } $stmt->bind_param("s", $ip); $stmt->execute(); $stmt->store_result(); if ($stmt->num_rows > 0) { http_response_code(403); echo "Access denied."; exit; } $stmt->close(); } // ============================================================================= // UTILITY FUNCTIONS - Comments & Misc // ============================================================================= function getCommentCount($page_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT COUNT(*) as total FROM comments WHERE page_id = ?"); if (!$stmt) { return 0; } $stmt->bind_param("i", $page_id); $stmt->execute(); $stmt->bind_result($count); $stmt->fetch(); $stmt->close(); return (int)($count ?? 0); } function hasPhoneNumber($user_id) { $conn = openDatabaseConnection(); $stmt = $conn->prepare("SELECT phone_number FROM users WHERE user_id = ? LIMIT 1"); if (!$stmt) { return false; } $stmt->bind_param("i", $user_id); $stmt->execute(); $stmt->bind_result($phone_number); $stmt->fetch(); $stmt->close(); return !empty($phone_number); } function getResultFromTable($table, $column, $match, $identifier) { $conn = openDatabaseConnection(); $sql = "SELECT `$column` FROM `$table` WHERE `$match` = ? LIMIT 1"; $stmt = $conn->prepare($sql); if (!$stmt) { return null; } $stmt->bind_param('i', $identifier); $stmt->execute(); $stmt->bind_result($result); $stmt->fetch(); $stmt->close(); return $result; } // ============================================================================= // CRYPTOGRAPHY FUNCTIONS // ============================================================================= function encryptData($input, $salt) { $method = "AES-256-CBC"; $key = hash('sha256', $salt, true); $iv = substr(hash('sha256', $salt . 'iv'), 0, 16); $encrypted = openssl_encrypt($input, $method, $key, OPENSSL_RAW_DATA, $iv); return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($encrypted)); } function decryptData($input, $salt) { $method = "AES-256-CBC"; $key = hash('sha256', $salt, true); $iv = substr(hash('sha256', $salt . 'iv'), 0, 16); $encrypted = base64_decode(str_replace(['-', '_', ''], ['+', '/', '='], $input)); return openssl_decrypt($encrypted, $method, $key, OPENSSL_RAW_DATA, $iv); } function getNextOpenDayDate() { $conn = openDatabaseConnection(); $result = $conn->query("SELECT open_day_date FROM open_days WHERE open_day_date > CURDATE() ORDER BY open_day_date ASC LIMIT 1"); if ($result && $result->num_rows > 0) { $row = $result->fetch_assoc(); return $row['open_day_date']; } return date('Y-m-d', strtotime('+1 week')); } function getPrice($course, $userType) { $conn = openDatabaseConnection(); $column = ($userType === 'member') ? 'member_price' : 'non_member_price'; $stmt = $conn->prepare("SELECT `$column` FROM prices WHERE course_name = ? LIMIT 1"); if (!$stmt) { return 'Contact us'; } $stmt->bind_param('s', $course); $stmt->execute(); $stmt->bind_result($price); $stmt->fetch(); $stmt->close(); return $price ?? 'Contact us'; }