diff --git a/Dockerfile b/Dockerfile index e29d064d6b5e3eaafad16cd0da74d5ab9db3f8e4..1d2b0aa6ff4ad1548abfb3c16a5a76a2509afb21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,11 @@ -FROM php:8.0-apache +FROM php:8.1-apache + +RUN apt-get update && apt-get upgrade -y +RUN apt-get install -y libxml2-dev libpq-dev +RUN docker-php-ext-install pgsql pdo pdo_pgsql && docker-php-ext-enable pgsql pdo pdo_pgsql +RUN a2enmod rewrite && service apache2 restart +RUN chown -R :www-data /var/www/html/ -RUN docker-php-ext-install pdo pdo_mysql \ No newline at end of file +WORKDIR /var + +EXPOSE 80 \ No newline at end of file diff --git a/app/Models/Event.php b/app/Models/Event.php deleted file mode 100644 index 94ec0d38200f8e5d4b30acc731426dd08ce58f3c..0000000000000000000000000000000000000000 --- a/app/Models/Event.php +++ /dev/null @@ -1,216 +0,0 @@ -<?php - -require_once(__DIR__ . '/../../db/connect.php'); -require_once(__DIR__ . '/../util.php'); - -class EventModel { - - public function createEvent($event_name, $stock, $event_price, $event_date, $event_location, $gambar, $vid) { - global $db; - $success = true; - - if ($gambar !== null && isset($gambar['name']) && isset($gambar['tmp_name'])) { - $imageFilePath = '../assets/images/' . $gambar['name']; - - // Move the uploaded file to the desired directory - if (move_uploaded_file($gambar['tmp_name'], $imageFilePath)) { - echo "File uploaded successfully"; - } else { - echo "Error moving file to destination"; - $imageFilePath = null; // Set to null if there's an error - } - } else { - echo "No image uploaded"; - $imageFilePath = null; // Set to null if no file is uploaded - } - - if ($vid !== null && isset($vid['name']) && isset($vid['tmp_name'])) { - $vidFilePath = '../assets/videos/' . $vid['name']; - - // Move the uploaded file to the desired directory - if (move_uploaded_file($vid['tmp_name'], $vidFilePath)) { - echo "File uploaded successfully"; - } else { - echo "Error moving file to destination"; - $vidFilePath = null; // Set to null if there's an error - } - } else { - echo "No video uploaded"; - $vidFilePath = null; // Set to null if no file is uploaded - } - - if ($imageFilePath === null || $vidFilePath === null) { - $success = false; - return $success; - } - - $stmt = $db->prepare("INSERT INTO events (event_name, event_stock, event_price, event_date, event_location, gambar, vid) VALUES (?, ?, ?, ?, ?, ?, ?)"); - - if ($stmt->execute([$event_name, $stock, $event_price, $event_date, $event_location, $imageFilePath, $vidFilePath])) { - echo "Event created successfully"; - return $success; - } else { - echo "Error creating event: " . print_r($stmt->errorInfo(), true); - $success = false; - return $success; - } - } - - public function updateEvent($event_id, $event_name, $event_price, $event_date, $event_location, $gambar, $vid) { - global $db; - $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); - - echo "Updating Event with ID: $event_id, Name: $event_name, Price: $event_price, Date: $event_date, Location: $event_location"; - - if ($gambar !== null && isset($gambar['name']) && isset($gambar['tmp_name'])) { - $imageFilePath = '../assets/images/' . $gambar['name']; - - // Move the uploaded file to the desired directory - if (move_uploaded_file($gambar['tmp_name'], $imageFilePath)) { - echo "File uploaded successfully<br>"; - } else { - echo "Error moving file to destination<br>"; - $imageFilePath = null; // Set to null if there's an error - } - } else { - echo "No image uploaded<br>"; - $imageFilePath = null; // Set to null if no file is uploaded - } - - if ($vid !== null && isset($vid['name']) && isset($vid['tmp_name'])) { - $vidFilePath = '../assets/videos/' . $vid['name']; - - // Move the uploaded file to the desired directory - if (move_uploaded_file($vid['tmp_name'], $vidFilePath)) { - echo "File uploaded successfully<br>"; - } else { - echo "Error moving file to destination<br>"; - $vidFilePath = null; // Set to null if there's an error - } - } else { - echo "No video uploaded<br>"; - $vidFilePath = null; // Set to null if no file is uploaded - } - - // chek wheter image or video is null or not - if ($imageFilePath === null && $vidFilePath === null) { - $sql = "UPDATE events SET event_name = '$event_name', event_price = '$event_price', event_date = '$event_date', event_location = '$event_location' WHERE event_id = $event_id"; - } elseif ($imageFilePath === null) { - $sql = "UPDATE events SET event_name = '$event_name', event_price = '$event_price', event_date = '$event_date', event_location = '$event_location', vid = '$vidFilePath' WHERE event_id = $event_id"; - } elseif ($vidFilePath === null) { - $sql = "UPDATE events SET event_name = '$event_name', event_price = '$event_price', event_date = '$event_date', event_location = '$event_location', gambar = '$imageFilePath' WHERE event_id = $event_id"; - } else { - $sql = "UPDATE events SET event_name = '$event_name', event_price = '$event_price', event_date = '$event_date', event_location = '$event_location', gambar = '$imageFilePath', vid = '$vidFilePath' WHERE event_id = $event_id"; - } - - $rowCount = $db->exec($sql); - - if ($rowCount !== false) { - echo "Event updated successfully. Rows affected: $rowCount"; - } else { - echo "Error updating event: " . print_r($db->errorInfo(), true); - } - return "Event updated successfully"; - } - - - - public function deleteEvent($eventId) { - global $db; - - try { - // Delete associated pembelian records - $stmtPembelian = $db->prepare("DELETE FROM pembelian WHERE ticket_id IN (SELECT ticket_id FROM tickets WHERE event_id = ?)"); - $stmtPembelian->execute([$eventId]); - - // Delete associated tickets - $stmtTickets = $db->prepare("DELETE FROM tickets WHERE event_id = ?"); - $stmtTickets->execute([$eventId]); - - // Delete the event - $stmtEvent = $db->prepare("DELETE FROM events WHERE event_id = ?"); - $stmtEvent->execute([$eventId]); - - echo "Event, associated tickets, and pembelian records deleted successfully<br>"; - - return "Event, associated tickets, and pembelian records deleted successfully"; - } catch (PDOException $e) { - echo "Error: " . $e->getMessage() . "<br>"; - - return "Error: " . $e->getMessage(); - } - } - - public function getAllEvents() { - global $db; - $stmt = $db->prepare("SELECT * FROM events"); - $stmt->execute(); - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } - - public function getEvent($eventId) { - global $db; - $stmt = $db->prepare("SELECT * FROM events WHERE event_id = ?"); - $stmt->execute([$eventId]); - return $stmt->fetch(PDO::FETCH_ASSOC); - } - - public function getLastEventId() { - global $db; - $stmt = $db->prepare("SELECT event_id FROM events ORDER BY event_id DESC LIMIT 1"); - $stmt->execute(); - return $stmt->fetch(PDO::FETCH_ASSOC)['event_id']; - } - - public function searchEvents($searchQuery, $sortKey, $minStock) { - global $db; - - try { - $sql = "SELECT * FROM events WHERE 1"; // Start with a true condition - - // Add search condition - if (!empty($searchQuery)) { - $sql .= " AND (LOWER(event_name) LIKE CONCAT('%', :query, '%') OR LOWER(event_location) LIKE CONCAT('%', :query, '%'))"; - } - - - // Add filter condition - if ($minStock !== null) { - $sql .= " AND event_stock >= :minStock"; - } - - // Add sort condition - if ($sortKey === 'name') { - $sql .= " ORDER BY event_name ASC"; - } elseif ($sortKey === 'location') { - $sql .= " ORDER BY event_location ASC"; - } - - $stmt = $db->prepare($sql); - - // Bind search query parameter - if (!empty($searchQuery)) { - $lowerSearchQuery = strtolower("%" . $searchQuery . "%"); - $stmt->bindParam(':query', $lowerSearchQuery, PDO::PARAM_STR); - } - - // Bind filter parameter - if ($minStock !== null) { - $stmt->bindParam(':minStock', $minStock, PDO::PARAM_INT); - } - - $stmt->execute(); - - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } catch (PDOException $e) { - throw new Exception("Error searching events: " . $e->getMessage()); - } - } - - - - -} -?> - - diff --git a/app/Models/Pembelian.php b/app/Models/Pembelian.php deleted file mode 100644 index 0fcf741d91a4773be623aefe0029031038b12efb..0000000000000000000000000000000000000000 --- a/app/Models/Pembelian.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php -// app/models/Pembelian.php - -require_once(__DIR__ . '/../../db/connect.php'); -require_once(__DIR__ . '/../util.php'); - -class PembelianModel { - public function createPembelian($ticketId, $userId, $createdTime) { - global $db; - - $stmt = $db->prepare("INSERT INTO pembelian (ticket_id, user_id, pembelian_created_time) VALUES (?, ?, ?)"); - if ($stmt->execute([$ticketId, $userId, $createdTime])) { - $stmt = $db->prepare("SELECT event_id FROM tickets WHERE ticket_id = ?"); - $stmt->execute([$ticketId]); - $result = $stmt->fetch(PDO::FETCH_ASSOC); - - if ($result) { - $eventId = $result['event_id']; - - // Decrement the event's stock by 1 - $stmt = $db->prepare("UPDATE events SET event_stock = event_stock - 1 WHERE event_id = ?"); - return $stmt->execute([$eventId]); - } - } - } - - public function getPembelian($pembelianId) { - global $db; - - $stmt = $db->prepare("SELECT * FROM pembelian WHERE pembelian_id = ?"); - $stmt->execute([$pembelianId]); - - return $stmt->fetch(PDO::FETCH_ASSOC); - } - - public function updatePembelian($pembelianId, $ticketId, $userId, $createdTime) { - global $db; - - $stmt = $db->prepare("UPDATE pembelian SET ticket_id = ?, user_id = ?, pembelian_created_time = ? WHERE pembelian_id = ?"); - $stmt->execute([$ticketId, $userId, $createdTime, $pembelianId]); - - return "Pembelian updated successfully"; - } - - public function deletePembelian($pembelianId) { - global $db; - - $stmt = $db->prepare("DELETE FROM pembelian WHERE pembelian_id = ?"); - $stmt->execute([$pembelianId]); - - return "Pembelian deleted successfully"; - } - - public function getAllPembelian(){ - global $db; - $stmt = $db->prepare("SELECT * FROM pembelian"); - $stmt->execute(); - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } - - public function getAllPembelianWithDetails(){ - global $db; - $stmt = $db->prepare("SELECT * FROM pembelian JOIN tickets ON pembelian.ticket_id = tickets.ticket_id JOIN events ON tickets.event_id = events.event_id ORDER BY pembelian_created_time DESC"); - $stmt->execute(); - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } - - public function getPembelianByUserId($userId){ - global $db; - $stmt = $db->prepare("SELECT * FROM pembelian JOIN tickets ON pembelian.ticket_id = tickets.ticket_id JOIN events ON tickets.event_id = events.event_id WHERE user_id = ? ORDER BY pembelian_created_time DESC"); - $stmt->execute([$userId]); - return $stmt->fetchAll(PDO::FETCH_ASSOC); - } -} -?> diff --git a/app/Views/login/login.php b/app/Views/login/login.php deleted file mode 100644 index 2ca035a560f262411451a7f910311c690fa21fdb..0000000000000000000000000000000000000000 --- a/app/Views/login/login.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - session_start(); -?> -<!DOCTYPE html> -<html lang="en"> - - <head> - <title>Login • TICKET KU</title> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <link rel="stylesheet" type="text/css" href="../../../styles/auth.css"> - </head> - - <body> - <div class="login-container"> - <h1>Login</h1> - <form id="loginForm" method="post" action="../../router.php"> - <!-- Aslinya email atau username bisa(?) --> - <label for="email">Email or Username</label> - <input type="text" id="identifier" name="loginIdentifier" required> - - <label for="password">Password</label> - <input type="password" id="password" name="loginPassword" required> - - <?php - // Check if there is an error message in the session - if (isset($_SESSION['message'])) { - echo '<p>' . $_SESSION['message'] . '</p>'; - unset($_SESSION['message']); // Remove the error message from the session - } - ?> - <button type="submit" name="userAction" value="login">Login</button> - </form> - <p>Don't have an account? <a href="register.php">Register</a></p> - </div> - </body> -</html> \ No newline at end of file diff --git a/app/router.php b/app/router.php deleted file mode 100644 index 7156e5c4dea8e7de894027f76c3b7fb0b37c0ccd..0000000000000000000000000000000000000000 --- a/app/router.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -require_once './Controllers/PembelianController.php'; -require_once './Controllers/TicketController.php'; -require_once './Controllers/UserController.php'; -require_once './Controllers/EventController.php'; - -$eventController = new EventController(); -$pembelianController = new PembelianController(); -$ticketController = new TicketController(); -$userController = new UserController(); - -if ($_SERVER["REQUEST_METHOD"] == "POST") { - if (isset($_POST["eventAction"])) { - $eventController->handleRequest(); - } elseif (isset($_POST["ticketAction"])) { - $ticketController->handleRequest(); - } elseif (isset($_POST["userAction"])) { - $userController->handleRequest(); - } elseif (isset($_POST["purchaseAction"])) { - $pembelianController->handleRequest(); - } - -} elseif ($_SERVER["REQUEST_METHOD"] == "GET") { - if (isset($_GET["eventAction"]) && isset($_GET["eventId"])) { - $eventController->handleRequest(); - } elseif (isset($_GET["ticketAction"])) { - $ticketController->handleRequest(); - } elseif (isset($_GET["userAction"])) { - $userController->handleRequest(); - } -} -?> \ No newline at end of file diff --git a/app/util.php b/app/util.php deleted file mode 100644 index da3c6d57c9624c8dcc4ed19faa9297280b76715d..0000000000000000000000000000000000000000 --- a/app/util.php +++ /dev/null @@ -1,13 +0,0 @@ -<?php -function preprocess($str) { - return str_replace(' ', '%20', $str); -} - -function formatPrice($price) { - return number_format($price,0,',','.'); -} - -function isEmailValid($email) { - return filter_var($email, FILTER_VALIDATE_EMAIL); -} -?> \ No newline at end of file diff --git a/database/1-create-table-users.sql b/database/1-create-table-users.sql new file mode 100644 index 0000000000000000000000000000000000000000..b138fb00e6995f74d60e1779e04cb399fefdff38 --- /dev/null +++ b/database/1-create-table-users.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS users ( + user_ID SERIAL PRIMARY KEY, + user_name VARCHAR(255), + username VARCHAR(255) UNIQUE, + user_email VARCHAR(255) UNIQUE, + user_hashedPass VARCHAR(255), + isAdmin BOOLEAN +); \ No newline at end of file diff --git a/database/2-create-table-events.sql b/database/2-create-table-events.sql new file mode 100644 index 0000000000000000000000000000000000000000..80c7f2615c49a6f979ce5645488165c1d3e55e7f --- /dev/null +++ b/database/2-create-table-events.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS events ( + event_id SERIAL PRIMARY KEY, + event_name VARCHAR(255), + event_stock INT, + event_price INT, + event_date TIMESTAMP, + event_location VARCHAR(255), + gambar VARCHAR(255), + vid VARCHAR(255) +); \ No newline at end of file diff --git a/database/3-create-table-tickets.sql b/database/3-create-table-tickets.sql new file mode 100644 index 0000000000000000000000000000000000000000..0de3886b985ffe29f246aae4482fd3e48014d84d --- /dev/null +++ b/database/3-create-table-tickets.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS tickets ( + ticket_id SERIAL PRIMARY KEY, + ticket_name VARCHAR(255), + event_id INT, + FOREIGN KEY (event_id) REFERENCES events(event_id) ON DELETE SET NULL +); diff --git a/database/4-create-table-pembelian.sql b/database/4-create-table-pembelian.sql new file mode 100644 index 0000000000000000000000000000000000000000..05e8eacab283585a2c45d7a7c8cad6a0ea321475 --- /dev/null +++ b/database/4-create-table-pembelian.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS pembelian ( + pembelian_id SERIAL PRIMARY KEY, + ticket_id INT, + user_id INT, + pembelian_created_time TIMESTAMP, + FOREIGN KEY (ticket_id) REFERENCES tickets(ticket_id), + FOREIGN KEY (user_id) REFERENCES users(user_ID) ON DELETE SET NULL +); diff --git a/database/5-create-table-subscription.sql b/database/5-create-table-subscription.sql new file mode 100644 index 0000000000000000000000000000000000000000..9f78283a64a43410fd26416c7ea047a88b24ef8f --- /dev/null +++ b/database/5-create-table-subscription.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS subscription ( + creator_id INT NOT NULL, + subscriber_id INT NOT NULL, + status VARCHAR(10) NOT NULL DEFAULT 'PENDING', + creator_name VARCHAR(255) NOT NULL, + PRIMARY KEY (creator_id, subscriber_id), + FOREIGN KEY (subscriber_id) REFERENCES users(user_ID) ON DELETE CASCADE +); diff --git a/database/6-seed.sql b/database/6-seed.sql new file mode 100644 index 0000000000000000000000000000000000000000..36241df86b2e292f4b88fdba181e83692d30af87 --- /dev/null +++ b/database/6-seed.sql @@ -0,0 +1,36 @@ +-- Generate and insert 100 dummy events with random data +DO $$ +DECLARE + i INT; +BEGIN + FOR i IN 1..100 LOOP + INSERT INTO events (event_name, event_stock, event_price, event_date, event_location, gambar, vid) + VALUES ( + 'Event ' || i, + FLOOR(RANDOM() * 10) + 1, + FLOOR(RANDOM() * 91) + 10, + NOW() + (i || ' days')::INTERVAL, + 'Location ' || i, + 'assets/images/' || (i % 16 + 1) || '.jpg', + 'assets/videos/video.mp4' + ); + + -- Generate and insert tickets corresponding to the event's event_stock + FOR j IN 1..(FLOOR(RANDOM() * 10) + 1) LOOP + INSERT INTO tickets (ticket_name, event_id) + VALUES ( + 'Ticket ' || j || ' for Event ' || i, + (SELECT MAX(event_id) FROM events) + ); + END LOOP; + END LOOP; +END $$; + +-- Insert user data +INSERT INTO users (user_name, username, user_email, user_hashedPass, isAdmin) +VALUES + ('John Doe', 'john_doe', 'john@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'true'), + ('Jane Smith', 'jane_smith', 'jane@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'false'), + ('Admin User', 'admin_user', 'admin@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'true'), + ('Alice Johnson', 'alice', 'alice@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'false'), + ('Bob Williams', 'bob', 'bob@example.com', '$2y$10$8sA2N5Sx/1zMQv2yrTDAaOFlbGWECrrgB68axL.hBb78NhQdyAqWm', 'false'); diff --git a/db/connect.php b/db/connect.php deleted file mode 100644 index 7ab45efbe3d2a27d58375be1bff764bafec8698a..0000000000000000000000000000000000000000 --- a/db/connect.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - $host = 'db'; - $dbname = 'tubes1_WBD'; - $user = 'root'; - $pass = 'your_password'; - - try { - $db = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass); - - // Execute SQL statements from init.sql - $sqlInit = file_get_contents(__DIR__ . '/init.sql'); - $db->exec($sqlInit); - - // echo "Connected successfully and database initialized!<br/>"; - } catch (PDOException $e) { - // echo "Connection failed: " . $e->getMessage(); - } - -?> diff --git a/db/data.php b/db/data.php deleted file mode 100644 index 2b8c7e4f4a634b064b2c17efcd8c5b352b7c3b4c..0000000000000000000000000000000000000000 --- a/db/data.php +++ /dev/null @@ -1,79 +0,0 @@ -<?php -include 'connect.php'; - -// Make sure $db is defined and not null -if (isset($db)) { - try { - $db->beginTransaction(); - - // Insert events and tickets as before - $sqlEvent = <<<EOF - INSERT INTO events (event_name, event_stock, event_price, event_date, event_location, gambar, vid) VALUES - ('Music Concert', 2, 20, '2023-09-30 10:00:00', 'jakarta', 'assets/images/1.jpg', 'assets/videos/video.mp4'), - ('Art Exhibition', 2, 15, '2023-10-05 15:30:00', 'prancis', 'assets/images/2.png', 'assets/videos/video.mp4'), - ('Sports Tournament', 2, 40, '2023-11-12 18:45:00', 'italy', 'assets/images/3.jpg', 'assets/videos/video.mp4'), - ('Comedy Show', 2, 30, '2023-12-03 20:00:00', 'jakarta', 'assets/images/4.jpg', 'assets/videos/video.mp4'), - ('Tech Conference', 2, 60, '2024-01-18 14:15:00', 'ITB', 'assets/images/5.jpg', 'assets/videos/video.mp4'); - EOF; - - $sqlTicket = <<<EOF - INSERT INTO tickets (ticket_name, event_id) VALUES - ('General Admission', 1), - ('VIP Pass', 1), - ('Standard Ticket', 2), - ('Student Discount', 2), - ('Early Bird Special', 3), - ('Premium Access', 3), - ('Weekend Pass', 4), - ('Group Discount', 4), - ('Conference Pass', 5), - ('Exhibitor Pass', 5); - EOF; - - $db->exec($sqlEvent); - $db->exec($sqlTicket); - - // Dummy user data with hashed passwords - $userData = [ - ['John Doe', 'john_doe', 'john@example.com', password_hash('password_1', PASSWORD_DEFAULT), 1], - ['Jane Smith', 'jane_smith', 'jane@example.com', password_hash('password_2', PASSWORD_DEFAULT), 0], - ['Admin User', 'admin_user', 'admin@example.com', password_hash('password_3', PASSWORD_DEFAULT), 1], - ['Alice Johnson', 'alice', 'alice@example.com', password_hash('password_4', PASSWORD_DEFAULT), 0], - ['Bob Williams', 'bob', 'bob@example.com', password_hash('password_5', PASSWORD_DEFAULT), 0] - ]; - - $sqlUser = "INSERT INTO users (user_name, username, user_email, user_hashedPass, isAdmin) VALUES (?, ?, ?, ?, ?)"; - $stmt = $db->prepare($sqlUser); - - foreach ($userData as $user) { - $stmt->execute($user); - } - - $stmt->closeCursor(); - - // // Insert pembelian data - // $sqlPembelian = <<<EOF - // INSERT INTO pembelian (ticket_id, user_id, pembelian_created_time) VALUES - // (1, 1, '2023-10-01 12:30:00'), - // (3, 2, '2023-10-06 16:15:00'), - // (2, 3, '2023-11-15 20:00:00'), - // (5, 4, '2023-12-05 10:45:00'), - // (8, 5, '2024-01-20 08:30:00'); - // EOF; - - // $db->exec($sqlPembelian); - - // Commit the transaction - $db->commit(); - - echo "Successfully inserted dummy data.<br/>"; - } catch (PDOException $e) { - $db->rollBack(); - echo "Error: " . $e->getMessage(); - } - } else { - echo "Error: Database connection not established."; - } - - $db = null; -?> diff --git a/db/init.php b/db/init.php deleted file mode 100644 index d5efdd7fbee4a7978546eb4828d86c6a208c781c..0000000000000000000000000000000000000000 --- a/db/init.php +++ /dev/null @@ -1,26 +0,0 @@ -<?php -include 'connect.php'; - -$dotenvContents = file_get_contents(__DIR__ . '/../.env'); -$dotenvLines = explode("\n", $dotenvContents); - -foreach ($dotenvLines as $line) { - // Skip empty lines and comments - if (!empty($line) && strpos($line, '=') !== false && strpos($line, '#') !== 0) { - list($name, $value) = explode('=', $line, 2); - $_ENV[$name] = $value; - putenv("$name=$value"); - } -} - -error_reporting(E_ALL); -ini_set('display_errors', 1); - - -include 'reset.php'; -include 'data.php'; - -$db = null; - -// echo "Database initialization successful!"; -?> diff --git a/db/init.sql b/db/init.sql deleted file mode 100644 index 0beaedfc29604f9454f333b3a4411b5108553768..0000000000000000000000000000000000000000 --- a/db/init.sql +++ /dev/null @@ -1,48 +0,0 @@ -CREATE DATABASE IF NOT EXISTS tubes1_WBD; - -USE tubes1_WBD; - -CREATE TABLE IF NOT EXISTS events ( - event_id INT AUTO_INCREMENT PRIMARY KEY, - event_name CHAR(255), - event_stock INT, - event_price INT, - event_date DATETIME, - event_location CHAR(255), - gambar VARCHAR(255), - vid VARCHAR(255) -); - -CREATE TABLE IF NOT EXISTS tickets ( - ticket_id INT AUTO_INCREMENT PRIMARY KEY, - ticket_name CHAR(255), - event_id INT, - FOREIGN KEY (event_id) REFERENCES events(event_id) ON DELETE SET NULL -); - -CREATE TABLE IF NOT EXISTS users ( - user_ID INT AUTO_INCREMENT PRIMARY KEY, - user_name CHAR(255), - username CHAR(255) UNIQUE, - user_email VARCHAR(255) UNIQUE, - user_hashedPass CHAR(255), - isAdmin BOOLEAN -); - -CREATE TABLE IF NOT EXISTS pembelian ( - pembelian_id INT AUTO_INCREMENT PRIMARY KEY, - ticket_id INT, - user_id INT, - pembelian_created_time DATETIME, - FOREIGN KEY (ticket_id) REFERENCES tickets(ticket_id), - FOREIGN KEY (user_id) REFERENCES users(user_ID) ON DELETE SET NULL -); - -CREATE TABLE IF NOT EXISTS subscription ( - creator_id int NOT NULL, - subscriber_id int NOT NULL, - status enum('PENDING','ACCEPTED','REJECTED') NOT NULL DEFAULT 'PENDING', - creator_name char(255) NOT NULL, - PRIMARY KEY (creator_id, subscriber_id), - FOREIGN KEY (subscriber_id) REFERENCES users(user_ID) ON DELETE CASCADE -); \ No newline at end of file diff --git a/db/reset.php b/db/reset.php deleted file mode 100644 index 1e98b7a351e2e637d0fa059e489aad7e4f08635b..0000000000000000000000000000000000000000 --- a/db/reset.php +++ /dev/null @@ -1,15 +0,0 @@ -<?php - include 'connect.php'; - - try { - $db->exec("DROP TABLE IF EXISTS pembelian"); - $db->exec("DROP TABLE IF EXISTS tickets"); - $db->exec("DROP TABLE IF EXISTS events"); - $db->exec("DROP TABLE IF EXISTS users"); - - // echo "Successfully reset the database<br/>"; - } catch (PDOException $e) { - // echo "Error: " . $e->getMessage(); - } - $db = null; -?> \ No newline at end of file diff --git a/src/.htaccess b/src/.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..122631ddccca95f9c7deb4126fa8f005bb799d5f --- /dev/null +++ b/src/.htaccess @@ -0,0 +1,13 @@ +DirectoryIndex index.php + +RewriteEngine On + +RewriteBase / + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d + +RewriteRule ^(.*)$ index.php [QSA] + +php_value post_max_size 16M +php_value upload_max_filesize 16M \ No newline at end of file diff --git a/styles/auth.css b/src/Client/auth.css similarity index 100% rename from styles/auth.css rename to src/Client/auth.css diff --git a/app/Views/template/event.php b/src/Client/components/event.php similarity index 100% rename from app/Views/template/event.php rename to src/Client/components/event.php diff --git a/app/Views/template/footer.php b/src/Client/components/footer.php similarity index 100% rename from app/Views/template/footer.php rename to src/Client/components/footer.php diff --git a/app/Views/template/history.php b/src/Client/components/history.php similarity index 100% rename from app/Views/template/history.php rename to src/Client/components/history.php diff --git a/app/Views/template/navbar.php b/src/Client/components/navbar.php similarity index 90% rename from app/Views/template/navbar.php rename to src/Client/components/navbar.php index ec8dd2abb5c9159fc789683ffbc72588471a9771..d8b9f315cf42e553115cdee21afd786606fc9056 100644 --- a/app/Views/template/navbar.php +++ b/src/Client/components/navbar.php @@ -7,7 +7,7 @@ <li><a href="/app/Views/history/history.php">History</a></li> <!-- Logout Button --> <li> - <form method="post" action="/app/router.php"> + <form method="post" action="/logout"> <button type="submit" name="userAction" value="logout">Logout</button> </form> </li> diff --git a/styles/container.css b/src/Client/container.css similarity index 100% rename from styles/container.css rename to src/Client/container.css diff --git a/styles/dropdown.css b/src/Client/dropdown.css similarity index 100% rename from styles/dropdown.css rename to src/Client/dropdown.css diff --git a/styles/footer.css b/src/Client/footer.css similarity index 100% rename from styles/footer.css rename to src/Client/footer.css diff --git a/styles/form.css b/src/Client/form.css similarity index 100% rename from styles/form.css rename to src/Client/form.css diff --git a/styles/global.css b/src/Client/global.css similarity index 100% rename from styles/global.css rename to src/Client/global.css diff --git a/styles/navbar.css b/src/Client/navbar.css similarity index 100% rename from styles/navbar.css rename to src/Client/navbar.css diff --git a/app/Views/event/create.php b/src/Client/pages/event/create.php similarity index 95% rename from app/Views/event/create.php rename to src/Client/pages/event/create.php index b486caa397b265e68072d2f4b78ee48646346236..75b6a10b2118c919657b3faf07bebba8ccdc766d 100644 --- a/app/Views/event/create.php +++ b/src/Client/pages/event/create.php @@ -1,5 +1,8 @@ <?php - session_start(); + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } ob_start(); if (!isset($_SESSION["user_id"])) { echo "here"; diff --git a/app/Views/event/update.php b/src/Client/pages/event/update.php similarity index 97% rename from app/Views/event/update.php rename to src/Client/pages/event/update.php index 3d638008c04ae889ba49048259af52b843fa0c29..84f1251705869979df5035fc2a46c0a1d5aaa7d7 100644 --- a/app/Views/event/update.php +++ b/src/Client/pages/event/update.php @@ -1,5 +1,8 @@ <?php - session_start(); + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } ob_start(); if (!isset($_SESSION["user_id"])) { echo "here"; diff --git a/app/Views/history/history.php b/src/Client/pages/history/history.php similarity index 96% rename from app/Views/history/history.php rename to src/Client/pages/history/history.php index b2e02634119d3edb062c656a5cdf4a3e41ac6c9d..10b8f5740cda2ae192de1506f1c1c55f56cca2cf 100644 --- a/app/Views/history/history.php +++ b/src/Client/pages/history/history.php @@ -1,5 +1,8 @@ <?php - session_start(); + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } ob_start(); if (!isset($_SESSION["user_id"])) { echo "here"; diff --git a/app/Views/home/home.php b/src/Client/pages/home/home.php similarity index 78% rename from app/Views/home/home.php rename to src/Client/pages/home/home.php index 701666b3ed1ed21f2fa786cc27dd08f05d741bf5..1cd9d381a804b98e292ce9be199e106815df1614 100644 --- a/app/Views/home/home.php +++ b/src/Client/pages/home/home.php @@ -1,22 +1,25 @@ <?php - session_start(); + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } ob_start(); if (!isset($_SESSION["user_id"])) { echo "here"; // User is not authenticated; redirect to login page - header("Location: /app/Views/login/login.php"); + header("Location: login"); ob_end_flush(); } - require_once '../../Controllers/PembelianController.php'; - require_once '../../Controllers/TicketController.php'; - require_once '../../Controllers/UserController.php'; - require_once '../../Controllers/EventController.php'; + require_once (__DIR__.'/../../../Server/Controllers/PembelianController.php'); + require_once (__DIR__.'/../../../Server/Controllers/TicketController.php'); + require_once (__DIR__.'/../../../Server/Controllers/UserController.php'); + require_once (__DIR__.'/../../../Server/Controllers/EventController.php'); $eventController = new EventController(); $pembelianController = new PembelianController(); $ticketController = new TicketController(); - $userController = new UserController(); + $userController = new \Server\Controllers\UserController(); // Handle search query $searchQuery = isset($_GET['search']) ? $_GET['search'] : ''; @@ -36,7 +39,7 @@ $currentPage = $paginationData['page']; $maxPage = $paginationData['maxpage']; - $isAdmin = $userController->getUser($_SESSION['user_id'])['isAdmin']; + $isAdmin = $userController->getUser($_SESSION['user_id'])['isadmin']; ?> <!DOCTYPE html> @@ -46,20 +49,20 @@ <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>HOME • TICKET KU</title> - <link rel="stylesheet" type="text/css" href="/../../styles/global.css"> - <link rel="stylesheet" type="text/css" href="/../../styles/form.css"> - <link rel="stylesheet" type="text/css" href="/../../styles/footer.css"> - <link rel="stylesheet" type="text/css" href="/../../styles/navbar.css"> - <link rel="stylesheet" type="text/css" href="/../../styles/container.css"> - <link rel="stylesheet" type="text/css" href="/../../styles/auth.css"> - <link rel="stylesheet" type="text/css" href="/../../styles/dropdown.css"> - <link rel="stylesheet" type="text/css" href="/../../styles/pagination.css"> - <link rel="stylesheet" type="text/css" href="/../../styles/media.css"> + <link rel="stylesheet" type="text/css" href="/../../global.css"> + <link rel="stylesheet" type="text/css" href="/../../form.css"> + <link rel="stylesheet" type="text/css" href="/../../footer.css"> + <link rel="stylesheet" type="text/css" href="/../../navbar.css"> + <link rel="stylesheet" type="text/css" href="/../../container.css"> + <link rel="stylesheet" type="text/css" href="/../../auth.css"> + <link rel="stylesheet" type="text/css" href="/../../dropdown.css"> + <link rel="stylesheet" type="text/css" href="/../../pagination.css"> + <link rel="stylesheet" type="text/css" href="/../../media.css"> </head> <body> <!-- Navbar --> - <?php include '../template/navbar.php';?> + <?php include (__DIR__.'/../../components/navbar.php');?> <div class="main-content"> <div class="column"> @@ -67,19 +70,20 @@ <button onclick="openCreateEventPage()" id="createEventBtn" class="admin">Create Event</button> <?php endif; ?> <div class="row"> - <input type="text" id="searchInput" placeholder="Search.." value="<?= htmlspecialchars($searchQuery)?>" style="width:250%;"> + <input type="text" id="searchInput" placeholder="Search.." value="<?= isset($searchQuery) ? htmlspecialchars($searchQuery) : '' ?>" style="width:250%;"> <select name="sort" id="sortSelect" class="styled-select"> <option value="" <?= empty($sortKey) ? 'selected' : '' ?>>No Sorting</option> <option value="name" <?= $sortKey === 'name' ? 'selected' : '' ?>>Sort by Name</option> <option value="location" <?= $sortKey === 'location' ? 'selected' : '' ?>>Sort by Location</option> </select> <!-- Change input type to "text" for minimum stock --> - <input type="text" id="minStockInput" name="min_stock" placeholder="Min Stock" value="<?= htmlspecialchars($minStock) ?>"> + <input type="text" id="minStockInput" name="min_stock" placeholder="Min Stock" value="<?= isset($minStock) ? htmlspecialchars($minStock) : 0 ?>" +"> <button type="submit" id="search-button">Search</button> </div> <?php foreach ($events as $event) : - include '../template/event.php'; + include (__DIR__.'/../../components/event.php'); endforeach;?> <div class="pagination"> @@ -112,7 +116,7 @@ </div> </div> - <?php include '../template/footer.php';?> + <?php include (__DIR__.'/../../components/footer.php');?> <script defer> function toggleMenu() { @@ -142,7 +146,7 @@ const sortKey = document.getElementById('sortSelect').value; // Construct the URL with search, min_stock, and sort parameters - const url = `/app/Views/home/home.php?search=${encodeURIComponent(searchQuery)}&min_stock=${encodeURIComponent(minStock)}&sort=${encodeURIComponent(sortKey)}`; + const url = `/home?search=${encodeURIComponent(searchQuery)}&min_stock=${encodeURIComponent(minStock)}&sort=${encodeURIComponent(sortKey)}`; // Redirect to the updated URL window.location.href = url; diff --git a/src/Client/pages/login/login.php b/src/Client/pages/login/login.php new file mode 100644 index 0000000000000000000000000000000000000000..017eba77ce35f882a7c4bf9b1cbf47ab1f9522d4 --- /dev/null +++ b/src/Client/pages/login/login.php @@ -0,0 +1,40 @@ +<?php +if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); +} +?> +<!DOCTYPE html> +<html lang="en"> + +<head> + <title>Login • TICKET KU</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" type="text/css" href="../../auth.css"> +</head> + +<body> + <div class="login-container"> + <h1>Login</h1> + <form id="loginForm" method="post" action="login"> + <!-- Aslinya email atau username bisa(?) --> + <label for="email">Email or Username</label> + <input type="text" id="identifier" name="loginIdentifier" required> + + <label for="password">Password</label> + <input type="password" id="password" name="loginPassword" required> + + <?php + // Check if there is an error message in the session + if (isset($_SESSION['message'])) { + echo '<p>' . $_SESSION['message'] . '</p>'; + unset($_SESSION['message']); // Remove the error message from the session + } + ?> + <button type="submit" name="userAction" value="login">Login</button> + </form> + <p>Don't have an account? <a href="register">Register</a></p> + </div> +</body> +</html> diff --git a/app/Views/login/register.php b/src/Client/pages/login/register.php similarity index 81% rename from app/Views/login/register.php rename to src/Client/pages/login/register.php index bdd3a0966d3145b309d50affbab88467c515ea29..660b237cd1d8bd7427fe0e40d4941d6492bc5095 100644 --- a/app/Views/login/register.php +++ b/src/Client/pages/login/register.php @@ -1,5 +1,8 @@ <?php - session_start(); + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } ?> <!DOCTYPE html> <html lang="en"> @@ -8,13 +11,13 @@ <title>Register • TICKET KU</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <link rel="stylesheet" type="text/css" href="../../../styles/auth.css"> + <link rel="stylesheet" type="text/css" href="../../auth.css"> </head> <body> <div class="register-container"> <h1>Register</h1> - <form id="registerForm" method="post" action="../../router.php"> + <form id="registerForm" method="post" action="register"> <label for="userName">Name</label> <input type="text" id="userName" name="userName" required> @@ -41,7 +44,7 @@ <button type="submit" name="userAction" value="createUser">Register</button> </form> - <p>Already have an account? <a href="login.php">Login</a></p> + <p>Already have an account? <a href="login">Login</a></p> </div> </body> </html> \ No newline at end of file diff --git a/app/Views/pembelian/pembelian.php b/src/Client/pages/pembelian/pembelian.php similarity index 96% rename from app/Views/pembelian/pembelian.php rename to src/Client/pages/pembelian/pembelian.php index 00d8ce4560b65c3e8d7c566cda67c1ad52ecbfbc..e8b2cfad7daad63cfd7b0bac446709cd840bc7c6 100644 --- a/app/Views/pembelian/pembelian.php +++ b/src/Client/pages/pembelian/pembelian.php @@ -1,5 +1,8 @@ <?php - session_start(); + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } ob_start(); if (!isset($_SESSION["user_id"])) { echo "here"; diff --git a/app/Views/profile/edit_profile.php b/src/Client/pages/profile/edit_profile.php similarity index 100% rename from app/Views/profile/edit_profile.php rename to src/Client/pages/profile/edit_profile.php diff --git a/app/Views/profile/view_profile.php b/src/Client/pages/profile/view_profile.php similarity index 95% rename from app/Views/profile/view_profile.php rename to src/Client/pages/profile/view_profile.php index 2eab3bcced344f665141e7c4879a072fa6607f73..7c3c492596ce2e88bac20d1e174093508d4ecf5c 100644 --- a/app/Views/profile/view_profile.php +++ b/src/Client/pages/profile/view_profile.php @@ -1,5 +1,8 @@ <?php - session_start(); + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } ob_start(); if (!isset($_SESSION["user_id"])) { echo "here"; diff --git a/styles/pagination.css b/src/Client/pagination.css similarity index 100% rename from styles/pagination.css rename to src/Client/pagination.css diff --git a/app/Controllers/EventController.php b/src/Server/Controllers/EventController.php similarity index 97% rename from app/Controllers/EventController.php rename to src/Server/Controllers/EventController.php index 2961a637e58138af8df7c7c26365bee9aff3b89e..0e5c9be2ce8f9e58f260092527fa55aa20a80549 100644 --- a/app/Controllers/EventController.php +++ b/src/Server/Controllers/EventController.php @@ -1,8 +1,7 @@ <?php -// app/Controllers/EventController.php ob_start(); -require_once(__DIR__ . '/../Models/Event.php'); +include(__DIR__ . '../../Models/Event.php'); require_once(__DIR__ . '/TicketController.php'); @@ -10,7 +9,7 @@ class EventController { private $eventModel; public function __construct() { - $this->eventModel = new EventModel(); + $this->eventModel = new \Server\Models\EventModel(); } public function createEvent($event_name, $stock, $event_price, $event_date, $event_location, $gambar, $vid){ diff --git a/src/Server/Controllers/HomeController.php b/src/Server/Controllers/HomeController.php new file mode 100644 index 0000000000000000000000000000000000000000..edb1b11791f9ff6066ce07cc2a7fc8906eccbc2d --- /dev/null +++ b/src/Server/Controllers/HomeController.php @@ -0,0 +1,11 @@ +<?php + +namespace Server\Controllers; + +class HomeController { + public function __construct(){} + public function home() + { + include (__DIR__.'/../../Client/pages/home/home.php'); + } +} \ No newline at end of file diff --git a/app/Controllers/PembelianController.php b/src/Server/Controllers/PembelianController.php similarity index 96% rename from app/Controllers/PembelianController.php rename to src/Server/Controllers/PembelianController.php index 9f5526def638e8436eec7807ffeff1778b9b542e..5f5701d1ca0c89316e0a11613fe54f96c3b84971 100644 --- a/app/Controllers/PembelianController.php +++ b/src/Server/Controllers/PembelianController.php @@ -10,11 +10,10 @@ class PembelianController { public function __construct() { - $this->pembelianModel = new PembelianModel(); + $this->pembelianModel = new \Server\Models\PembelianModel(); } public function createPembelian($ticketId, $userId, $createdTime) { - $pembelianModel = new PembelianModel(); return $this->pembelianModel->createPembelian($ticketId, $userId, $createdTime); } diff --git a/app/Controllers/SubscriptionController.php b/src/Server/Controllers/SubscriptionController.php similarity index 100% rename from app/Controllers/SubscriptionController.php rename to src/Server/Controllers/SubscriptionController.php diff --git a/app/Controllers/TicketController.php b/src/Server/Controllers/TicketController.php similarity index 96% rename from app/Controllers/TicketController.php rename to src/Server/Controllers/TicketController.php index 962586f10ebe910073345edf0e57faa66d2b421c..8d2944d1caebee23162052f5944727596ac0f275 100644 --- a/app/Controllers/TicketController.php +++ b/src/Server/Controllers/TicketController.php @@ -8,7 +8,7 @@ class TicketController { private $ticketModel; public function __construct() { - $this->ticketModel = new TicketModel(); + $this->ticketModel = new \Server\Models\TicketModel(); } public function createTicket($name, $eventId) { diff --git a/app/Controllers/UserController.php b/src/Server/Controllers/UserController.php similarity index 64% rename from app/Controllers/UserController.php rename to src/Server/Controllers/UserController.php index 3ae2e6c4c5ede827e7bf481525c9e222bda0eafd..6bf0731f73c13ca45eca90d6520f1afe6bcb44b4 100644 --- a/app/Controllers/UserController.php +++ b/src/Server/Controllers/UserController.php @@ -1,14 +1,15 @@ <?php -// app/controllers/userController.php -ob_start(); -require_once(__DIR__ . '/../Models/User.php'); + +namespace Server\Controllers; + +include (__DIR__.'/../Models/User.php'); class UserController { private $userModel; public function __construct() { - $this->userModel = new UserModel(); + $this->userModel = new \Server\Models\UserModel(); } public function createUser($name, $username, $email, $hashedPass, $isAdmin) { @@ -32,8 +33,15 @@ class UserController { } public function registerUser($name, $username, $email, $password, $isAdmin) { - return $this->createUser($name, $username, $email, password_hash($password,PASSWORD_DEFAULT), $isAdmin); + $hashedPassword = password_hash($password, PASSWORD_DEFAULT); + + if ($hashedPassword === false) { + return ['success' => false, 'message' => 'Password hashing failed']; + } + + return $this->createUser($name, $username, $email, $hashedPassword, $isAdmin); } + public function loginByEmail($email,$password) { $user = $this->userModel->getUserByEmail($email); @@ -45,18 +53,6 @@ class UserController { return "wrong credentials"; } } - - public function loginByUsername($username,$password) { - $user = $this->userModel->getUserByUsername($username); - if ($user !== false && password_verify($password, $user['user_hashedPass'])) { - session_start(); - $_SESSION["user_id"] = $user['user_ID']; - return "success"; - } else { - session_start(); - return "wrong credentials"; - } - } public function logout() { session_start(); @@ -72,6 +68,90 @@ class UserController { public function editProfile($user_id, $name, $username, $email) { return $this->userModel->editProfile($user_id, $name, $username, $email); } + + public function loginview() { + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } + // Check if the user is already logged in, redirect to home if true + if (isset($_SESSION['user_id'])) { + header("Location: /home"); + ob_end_flush(); + exit(); + } + + include (__DIR__.'/../../Client/pages/login/login.php'); + } + + public function login() { + // Check if the required parameters are set in the POST request + if (isset($_POST['loginIdentifier']) && isset($_POST['loginPassword'])) { + $emailOrUsername = $_POST['loginIdentifier']; + $password = $_POST['loginPassword']; + + if (filter_var($emailOrUsername, FILTER_VALIDATE_EMAIL)) { + $user = $this->userModel->getUserByEmail($emailOrUsername); + } else { + $user = $this->userModel->getUserByUsername($emailOrUsername); + } + + if ($user !== false) { + if (password_verify($password, $user['user_hashedpass'])) { + session_start(); + $_SESSION["user_id"] = $user['user_id']; + header("Location: /home"); + ob_end_flush(); + exit(); + } else { + session_start(); + $_SESSION['message'] = "Wrong Password"; + header("Location: /login"); + ob_end_flush(); + exit(); + } + } else { + session_start(); + $_SESSION['message'] = "Wrong credentials"; + header("Location: /login"); + ob_end_flush(); + exit(); + } + } else { + // Handle missing parameters + session_start(); + $_SESSION['message'] = "Missing login parameters"; + header("Location: /login"); + ob_end_flush(); + exit(); + } + } + + public function registerview() { + include (__DIR__."/../../Client/pages/login/register.php"); + } + + public function register() { + $userName = $_POST['userName']; + $userUsername = $_POST['userUsername']; + $userEmail = $_POST['userEmail']; + $userPassword = $_POST['userPassword']; + $isAdmin = isset($_POST['isAdmin']) ? 1 : 0; + $response = $this->registerUser($userName,$userUsername,$userEmail,$userPassword,$isAdmin); + + $success = $response['success']; + if($success){ + session_start(); + $_SESSION['message'] = "You have successfully registered. Please log in"; + header("Location:login"); + ob_end_flush(); + } else { + session_start(); + $_SESSION['error_message'] = $response['message']; + header("Location:register"); + ob_end_flush(); + } + } public function handleRequest() { if (isset($_POST['userAction'])) { diff --git a/src/Server/Models/Event.php b/src/Server/Models/Event.php new file mode 100644 index 0000000000000000000000000000000000000000..85a902113d132e4f336c19aa5caa940d90963c53 --- /dev/null +++ b/src/Server/Models/Event.php @@ -0,0 +1,176 @@ +<?php + +namespace Server\Models; + +use PDO; + +class EventModel extends Model { + + public function createEvent($event_name, $stock, $event_price, $event_date, $event_location, $gambar, $vid) { + $success = true; + + if ($gambar !== null && isset($gambar['name']) && isset($gambar['tmp_name'])) { + $imageFilePath = '../assets/images/' . $gambar['name']; + + if (move_uploaded_file($gambar['tmp_name'], $imageFilePath)) { + echo "File uploaded successfully"; + } else { + echo "Error moving file to destination"; + $imageFilePath = null; // Set to null if there's an error + } + } else { + echo "No image uploaded"; + $imageFilePath = null; // Set to null if no file is uploaded + } + + if ($vid !== null && isset($vid['name']) && isset($vid['tmp_name'])) { + $vidFilePath = '../assets/videos/' . $vid['name']; + + if (move_uploaded_file($vid['tmp_name'], $vidFilePath)) { + echo "File uploaded successfully"; + } else { + echo "Error moving file to destination"; + $vidFilePath = null; // Set to null if there's an error + } + } else { + echo "No video uploaded"; + $vidFilePath = null; // Set to null if no file is uploaded + } + + if ($imageFilePath === null || $vidFilePath === null) { + $success = false; + return $success; + } + + $stmt = $this->database->prepare("INSERT INTO events (event_name, event_stock, event_price, event_date, event_location, gambar, vid) VALUES (?, ?, ?, ?, ?, ?, ?)"); + + if ($stmt->execute([$event_name, $stock, $event_price, $event_date, $event_location, $imageFilePath, $vidFilePath])) { + echo "Event created successfully"; + return $success; + } else { + echo "Error creating event: " . print_r($stmt->errorInfo(), true); + $success = false; + return $success; + } + } + + public function updateEvent($event_id, $event_name, $event_price, $event_date, $event_location, $gambar, $vid) { + $sql = "UPDATE events SET event_name = ?, event_price = ?, event_date = ?, event_location = ?"; + + if ($gambar !== null && isset($gambar['name']) && isset($gambar['tmp_name'])) { + $imageFilePath = '../assets/images/' . $gambar['name']; + + if (move_uploaded_file($gambar['tmp_name'], $imageFilePath)) { + echo "File uploaded successfully<br>"; + } else { + echo "Error moving file to destination<br>"; + $imageFilePath = null; // Set to null if there's an error + } + + $sql .= ", gambar = ?"; + } + + if ($vid !== null && isset($vid['name']) && isset($vid['tmp_name'])) { + $vidFilePath = '../assets/videos/' . $vid['name']; + + if (move_uploaded_file($vid['tmp_name'], $vidFilePath)) { + echo "File uploaded successfully<br>"; + } else { + echo "Error moving file to destination<br>"; + $vidFilePath = null; // Set to null if there's an error + } + + $sql .= ", vid = ?"; + } + + $sql .= " WHERE event_id = ?"; + + $stmt = $this->database->prepare($sql); + + $params = [$event_name, $event_price, $event_date, $event_location]; + + if ($imageFilePath !== null) { + $params[] = $imageFilePath; + } + + if ($vidFilePath !== null) { + $params[] = $vidFilePath; + } + + $params[] = $event_id; + + $rowCount = $stmt->execute($params); + + if ($rowCount !== false) { + echo "Event updated successfully. Rows affected: $rowCount"; + } else { + echo "Error updating event: " . print_r($stmt->errorInfo(), true); + } + return "Event updated successfully"; + } + + public function deleteEvent($eventId) { + try { + // Delete associated records or perform necessary cleanup + + $stmtEvent = $this->database->prepare("DELETE FROM events WHERE event_id = ?"); + $stmtEvent->execute([$eventId]); + + echo "Event deleted successfully<br>"; + + return "Event deleted successfully"; + } catch (PDOException $e) { + echo "Error: " . $e->getMessage() . "<br>"; + + return "Error: " . $e->getMessage(); + } + } + + public function getAllEvents() { + $stmt = $this->database->prepare("SELECT * FROM events"); + $stmt->execute(); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + public function getEvent($eventId) { + $stmt = $this->database->prepare("SELECT * FROM events WHERE event_id = ?"); + $stmt->execute([$eventId]); + return $stmt->fetch(PDO::FETCH_ASSOC); + } + + public function getLastEventId() { + $stmt = $this->database->prepare("SELECT event_id FROM events ORDER BY event_id DESC LIMIT 1"); + $stmt->execute(); + return $stmt->fetch(PDO::FETCH_ASSOC)['event_id']; + } + + public function searchEvents($searchQuery, $sortKey, $minStock) { + try { + if ($minStock == null) { + $minStock = 0; + } + + $stmt = "SELECT * FROM events + WHERE (LOWER(event_name) LIKE LOWER(?) OR LOWER(event_location) LIKE LOWER(?)) + AND event_stock >= ?"; + + if (!empty($sortKey)) { + $stmt .= " ORDER BY "; + + if ($sortKey === 'name') { + $stmt .= "event_name ASC"; + } elseif ($sortKey === 'location') { + $stmt .= "event_location ASC"; + } + } + + $query = $this->database->prepare($stmt); + $query->execute(array('%'.$searchQuery.'%', '%'.$searchQuery.'%', $minStock)); + + return $query->fetchAll(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + throw new Exception("Error searching events: " . $e->getMessage()); + } + } + +} diff --git a/src/Server/Models/Model.php b/src/Server/Models/Model.php new file mode 100644 index 0000000000000000000000000000000000000000..fc2fe6b25246c1204f7827f0509c4d012a633c60 --- /dev/null +++ b/src/Server/Models/Model.php @@ -0,0 +1,22 @@ +<?php + +namespace Server\Models; + +use PDO; + +class Model { + protected $database; + + public function __construct() + { + $dsn = "pgsql:host=ticketku-php-db;port=5433;dbname=ticketku;"; + $user = "postgres"; + $password = "postgres"; + try { + $this->database = new PDO($dsn, $user, $password, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); + } catch (\PDOException $e) { + die($e->getMessage()); + } + } + +} diff --git a/src/Server/Models/Pembelian.php b/src/Server/Models/Pembelian.php new file mode 100644 index 0000000000000000000000000000000000000000..ed44a4bbb58d2b0d2228725a1dd768060e74e678 --- /dev/null +++ b/src/Server/Models/Pembelian.php @@ -0,0 +1,64 @@ +<?php + +namespace Server\Models; + +use PDO; + +class PembelianModel extends Model { + public function createPembelian($ticketId, $userId, $createdTime) { + $stmt = $this->database->prepare("INSERT INTO pembelian (ticket_id, user_id, pembelian_created_time) VALUES (?, ?, ?)"); + + if ($stmt->execute([$ticketId, $userId, $createdTime])) { + $stmt = $this->database->prepare("SELECT event_id FROM tickets WHERE ticket_id = ?"); + $stmt->execute([$ticketId]); + $result = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($result) { + $eventId = $result['event_id']; + + // Decrement the event's stock by 1 + $stmt = $this->database->prepare("UPDATE events SET event_stock = event_stock - 1 WHERE event_id = ?"); + return $stmt->execute([$eventId]); + } + } + } + + public function getPembelian($pembelianId) { + $stmt = $this->database->prepare("SELECT * FROM pembelian WHERE pembelian_id = ?"); + $stmt->execute([$pembelianId]); + + return $stmt->fetch(PDO::FETCH_ASSOC); + } + + public function updatePembelian($pembelianId, $ticketId, $userId, $createdTime) { + $stmt = $this->database->prepare("UPDATE pembelian SET ticket_id = ?, user_id = ?, pembelian_created_time = ? WHERE pembelian_id = ?"); + $stmt->execute([$ticketId, $userId, $createdTime, $pembelianId]); + + return "Pembelian updated successfully"; + } + + public function deletePembelian($pembelianId) { + $stmt = $this->database->prepare("DELETE FROM pembelian WHERE pembelian_id = ?"); + $stmt->execute([$pembelianId]); + + return "Pembelian deleted successfully"; + } + + public function getAllPembelian() { + $stmt = $this->database->prepare("SELECT * FROM pembelian"); + $stmt->execute(); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + public function getAllPembelianWithDetails() { + $stmt = $this->database->prepare("SELECT * FROM pembelian JOIN tickets ON pembelian.ticket_id = tickets.ticket_id JOIN events ON tickets.event_id = events.event_id ORDER BY pembelian_created_time DESC"); + $stmt->execute(); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } + + public function getPembelianByUserId($userId) { + $stmt = $this->database->prepare("SELECT * FROM pembelian JOIN tickets ON pembelian.ticket_id = tickets.ticket_id JOIN events ON tickets.event_id = events.event_id WHERE user_id = ? ORDER BY pembelian_created_time DESC"); + $stmt->execute([$userId]); + return $stmt->fetchAll(PDO::FETCH_ASSOC); + } +} diff --git a/app/Models/Subscription.php b/src/Server/Models/Subscription.php similarity index 100% rename from app/Models/Subscription.php rename to src/Server/Models/Subscription.php diff --git a/app/Models/Ticket.php b/src/Server/Models/Ticket.php similarity index 66% rename from app/Models/Ticket.php rename to src/Server/Models/Ticket.php index 4060c6ede2da98c4e084c8bef084f05fe8651aa4..388049a1f4b367092fa931cac237df96dcba19e0 100644 --- a/app/Models/Ticket.php +++ b/src/Server/Models/Ticket.php @@ -1,59 +1,47 @@ <?php -// app/models/Ticket.php -require_once(__DIR__ . '/../../db/connect.php'); +namespace Server\Models; +use PDO; -class TicketModel { +class TicketModel extends Model { public function createTicket($name, $eventId) { - global $db; - - $stmt = $db->prepare("INSERT INTO tickets (ticket_name, event_id) VALUES (?, ?)"); + $stmt = $this->database->prepare("INSERT INTO tickets (ticket_name, event_id) VALUES (?, ?)"); $stmt->execute([$name, $eventId]); return "Ticket created successfully"; } public function getTicket($ticketId) { - global $db; - - $stmt = $db->prepare("SELECT * FROM tickets WHERE ticket_id = ?"); + $stmt = $this->database->prepare("SELECT * FROM tickets WHERE ticket_id = ?"); $stmt->execute([$ticketId]); return $stmt->fetch(PDO::FETCH_ASSOC); } public function updateTicket($ticketId, $name, $eventId) { - global $db; - - $stmt = $db->prepare("UPDATE tickets SET ticket_name = ?, event_id = ? WHERE ticket_id = ?"); + $stmt = $this->database->prepare("UPDATE tickets SET ticket_name = ?, event_id = ? WHERE ticket_id = ?"); $stmt->execute([$name, $eventId, $ticketId]); return "Ticket updated successfully"; } public function updateTicketByEventId($eventId, $name) { - global $db; - - $stmt = $db->prepare("UPDATE tickets SET ticket_name = ? WHERE event_id = ?"); + $stmt = $this->database->prepare("UPDATE tickets SET ticket_name = ? WHERE event_id = ?"); $stmt->execute([$name, $eventId]); return "Ticket updated successfully"; } public function deleteTicket($ticketId) { - global $db; - - $stmt = $db->prepare("DELETE FROM tickets WHERE ticket_id = ?"); + $stmt = $this->database->prepare("DELETE FROM tickets WHERE ticket_id = ?"); $stmt->execute([$ticketId]); return "Ticket deleted successfully"; } public function getSmallestAvailableTicket($eventId) { - global $db; - - $stmt = $db->prepare(" + $stmt = $this->database->prepare(" SELECT t.*, e.* FROM tickets t JOIN events e ON t.event_id = e.event_id @@ -73,4 +61,3 @@ class TicketModel { return $stmt->fetch(PDO::FETCH_ASSOC); } } -?> diff --git a/app/Models/User.php b/src/Server/Models/User.php similarity index 69% rename from app/Models/User.php rename to src/Server/Models/User.php index cb3410b23a9c471bcbdda9d7cdec126657941759..818b24b9f3bd2248e51ebeac3aeb12b429a078d6 100644 --- a/app/Models/User.php +++ b/src/Server/Models/User.php @@ -1,20 +1,21 @@ <?php -// app/models/User.php -require_once(__DIR__ . '/../../db/connect.php'); +namespace Server\Models; +use PDO; + +include (__DIR__."/Model.php"); -class UserModel { - public function createUser($name, $username, $email, $hashedPass, $isAdmin) { - global $db; +class UserModel extends Model { + public function createUser($name, $username, $email, $hashedPass, $isAdmin) { $response = [ 'success'=> true, 'message'=> '' ]; try { - $stmt = $db->prepare("INSERT INTO users (user_name, username, user_email, user_hashedPass, isAdmin) VALUES (?, ?, ?, ?, ?)"); + $stmt = $this->database->prepare("INSERT INTO users (user_name, username, user_email, user_hashedPass, isAdmin) VALUES (?, ?, ?, ?, ?)"); $stmt->execute([$name, $username, $email, $hashedPass, $isAdmin]); $response['message'] = "User created successfully"; return $response; @@ -36,9 +37,7 @@ class UserModel { // User.php public function getUser($userId) { - global $db; - - $stmt = $db->prepare("SELECT * FROM users WHERE user_ID = ?"); + $stmt = $this->database->prepare("SELECT * FROM users WHERE user_ID = ?"); $stmt->execute([$userId]); if ($stmt) { @@ -56,54 +55,41 @@ class UserModel { } public function getUserByEmail($email) { - global $db; - - $stmt = $db->prepare("SELECT * FROM users WHERE user_email = ?"); + $stmt = $this->database->prepare("SELECT * FROM users WHERE user_email = ?"); $stmt->execute([$email]); return $stmt->fetch(PDO::FETCH_ASSOC); } public function getUserByUsername($username){ - global $db; - - $stmt = $db->prepare("SELECT * FROM users WHERE username = ?"); + $stmt = $this->database->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$username]); return $stmt->fetch(PDO::FETCH_ASSOC); } public function updateUser($userId, $name, $username, $email, $hashedPass, $isAdmin) { - global $db; - - $stmt = $db->prepare("UPDATE users SET user_name = ?, username = ?, user_email = ?, user_hashedPass = ?, isAdmin = ? WHERE user_ID = ?"); + $stmt = $this->database->prepare("UPDATE users SET user_name = ?, username = ?, user_email = ?, user_hashedPass = ?, isAdmin = ? WHERE user_ID = ?"); $stmt->execute([$name, $username, $email, $hashedPass, $isAdmin, $userId]); return "User updated successfully"; } public function editProfile($userId, $name, $username, $email) { - global $db; - - $stmt = $db->prepare("UPDATE users SET user_name = ?, username = ?, user_email = ? WHERE user_id = ?"); + $stmt = $this->database->prepare("UPDATE users SET user_name = ?, username = ?, user_email = ? WHERE user_id = ?"); return $stmt->execute([$name, $username, $email, $userId]); } public function deleteUser($userId) { - global $db; - - $stmt = $db->prepare("DELETE FROM users WHERE user_ID = ?"); + $stmt = $this->database->prepare("DELETE FROM users WHERE user_ID = ?"); $stmt->execute([$userId]); return "User deleted successfully"; } public function getAllUsers() { - global $db; - - $stmt = $db->query("SELECT * FROM users"); + $stmt = $this->database->query("SELECT * FROM users"); return $stmt->fetchAll(PDO::FETCH_ASSOC); } - } ?> diff --git a/src/Server/Router/Router.php b/src/Server/Router/Router.php new file mode 100644 index 0000000000000000000000000000000000000000..7849f64bc71a714ec681b609040178f0203db7c3 --- /dev/null +++ b/src/Server/Router/Router.php @@ -0,0 +1,69 @@ +<?php + +namespace Server\Router; + +class Router { + private array $handlers; + private const METHOD_GET = 'GET'; + private const METHOD_POST = 'POST'; + + public function get(string $path, $handler): void + { + $this->addHandler(self::METHOD_GET, $path, $handler); + } + + public function post(string $path, $handler): void + { + $this->addHandler(self::METHOD_POST, $path, $handler); + } + + private function addHandler(string $method, string $path, $handler): void + { + $this->handlers[$method.$path] = [ + 'path' => $path, + 'method' => $method, + 'handler' => $handler, + ]; + } + + public function run() + { + $requstUri = parse_url($_SERVER['REQUEST_URI']); + $requestPath = $requstUri['path']; + $method = $_SERVER['REQUEST_METHOD']; + + $callback = null; + foreach ($this->handlers as $handler) { + if($handler['path'] === $requestPath && $method === $handler['method']) { + $callback = $handler['handler']; + } + } + + if (is_string($callback)) { + $parts = explode('@', $callback); + if (is_array($parts)) { + $className = array_shift($parts); + $method = array_shift($parts); + + // Check if the class exists before creating an instance + if (class_exists($className)) { + $handler = new $className; + + // Check if the method exists before setting the callback + if (method_exists($handler, $method)) { + $callback = [$handler, $method]; + } + } + } + } + + if(!$callback) { + include 'Client/pages/Errors/NotFound.php'; + return; + } + + call_user_func_array($callback, [ + array_merge($_GET, $_POST) + ]); + } +} \ No newline at end of file diff --git a/src/Server/web.php b/src/Server/web.php new file mode 100644 index 0000000000000000000000000000000000000000..d3dbe64a0333eb86605abd2ca487bc32fc95b9e7 --- /dev/null +++ b/src/Server/web.php @@ -0,0 +1,55 @@ +<?php + +declare(strict_types=1); + +include (__DIR__."/Router/Router.php"); +include (__DIR__."/Controllers/UserController.php"); +include (__DIR__."/Controllers/EventController.php"); +include (__DIR__."/Controllers/HomeController.php"); + +$router = new \Server\Router\Router(); + +function checkLoggedIn(): bool { + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } + return isset($_SESSION['user_id']); +} + +$router->get('/', function() { + header('Location: /home'); + exit(); +}); + +// Routes for HomeController +$router->get('/home', [new \Server\Controllers\HomeController(),'home']); + +// Routes for UserController +$router->get('/register', [new \Server\Controllers\UserController(), 'registerview']); +$router->post('/register', [new \Server\Controllers\UserController(), 'register']); +$router->post('/register/search-email', [checkLoggedIn(), [new \Server\Controllers\UserController(), 'findEmail']]); +$router->post('/register/search-username', [checkLoggedIn(), [new \Server\Controllers\UserController(), 'findByUsername']]); +$router->get('/login', [new \Server\Controllers\UserController(), 'loginview']); +$router->post('/login', [new \Server\Controllers\UserController(), 'login']); +$router->post('/logout', function() { + // No need to checkLoggedIn() here, as users can access this even if not logged in + if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); + } + session_destroy(); + header('Location: /login'); + exit(); +}); +$router->post('/profile', [checkLoggedIn(), [new \Server\Controllers\UserController(), 'viewProfile']]); +$router->post('/profile/edit', [checkLoggedIn(), [new \Server\Controllers\UserController(), 'editProfile']]); + +// Routes for EventsController +// $router->get('/events', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'eventList10view']]); +// $router->post('/events/create', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'createEvent']]); +// $router->post('/events/update', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'updateEvent']]); +// $router->post('/events/delete', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'deleteEvent']]); +// $router->get('/events/search', [checkLoggedIn(), [new \Server\Controllers\EventController(), 'searchview']]); + +$router->run(); diff --git a/src/index.php b/src/index.php new file mode 100644 index 0000000000000000000000000000000000000000..f6f970c24bd5e2e3475cc2b39d935ed8bb2f456e --- /dev/null +++ b/src/index.php @@ -0,0 +1,11 @@ +<?php +declare(strict_types=1); + +if (session_status() == PHP_SESSION_NONE) { + // If a session is not already started, start a new one + session_start(); +} + +include 'Server/web.php'; + +?>