This commit is contained in:
Flatlogic Bot 2026-01-22 07:43:24 +00:00
parent 73e14b3353
commit cdb0630e5e
4 changed files with 151 additions and 86 deletions

View File

@ -1,17 +1,51 @@
<?php
// Generated by setup_mariadb_project.sh — edit as needed.
define('DB_HOST', '127.0.0.1');
define('DB_NAME', 'app_37650');
define('DB_USER', 'app_37650');
define('DB_PASS', '4edb6fac-49c4-44d0-9b3e-6c6f933a7200');
// db/config.php
// Database configuration with fallback for XAMPP/Localhost
// 1. Try environment variables (for Cloud/VM environments)
$db_host = getenv('DB_HOST');
$db_name = getenv('DB_NAME');
$db_user = getenv('DB_USER');
$db_pass = getenv('DB_PASS');
// 2. Fallback to XAMPP defaults if not set
if ($db_host === false) $db_host = 'localhost';
if ($db_name === false) $db_name = 'car_dealership';
if ($db_user === false) $db_user = 'root';
if ($db_pass === false) $db_pass = ''; // Default XAMPP password is empty
// Define constants if not already defined
if (!defined('DB_HOST')) define('DB_HOST', $db_host);
if (!defined('DB_NAME')) define('DB_NAME', $db_name);
if (!defined('DB_USER')) define('DB_USER', $db_user);
if (!defined('DB_PASS')) define('DB_PASS', $db_pass);
function db() {
static $pdo;
if (!$pdo) {
$pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4', DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
}
return $pdo;
}
static $pdo;
if (!$pdo) {
try {
$dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4';
$pdo = new PDO($dsn, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
} catch (PDOException $e) {
// Special handling: If database not found, try connecting without DB name
// This is useful for the installer script to create the DB
if ($e->getCode() == 1049) { // Unknown database
$dsn_no_db = 'mysql:host='.DB_HOST.';charset=utf8mb4';
try {
$pdo = new PDO($dsn_no_db, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
} catch (PDOException $ex) {
die("Database connection failed: " . $ex->getMessage());
}
} else {
die("Database connection failed: " . $e->getMessage());
}
}
}
return $pdo;
}

View File

@ -1,40 +1,65 @@
<?php
// setup_project.php
// This script sets up the database tables and data as per the requirements.
// install.php
// Single installation file to set up the project on Windows (XAMPP) or Linux.
require_once 'includes/functions.php';
require_once 'db/config.php';
try {
$pdo = db();
echo "Database connection established.\n";
} catch (PDOException $e) {
die("Database connection failed: " . $e->getMessage() . "\n");
// Disable output buffering to show progress in real-time
if (function_exists('apache_setenv')) {
@apache_setenv('no-gzip', 1);
}
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);
echo "<!DOCTYPE html><html><head><title>Installation</title><style>body{font-family: sans-serif; padding: 20px; line-height: 1.6;} .success{color: green;} .error{color: red;} .step{margin-bottom: 10px;}</style></head><body>";
echo "<h1>Car Sells in Afghanistan - Installation</h1>";
try {
// 2. Drop existing tables to ensure a clean state
$pdo->exec("SET FOREIGN_KEY_CHECKS=0");
$pdo->exec("DROP TABLE IF EXISTS reviews");
$pdo->exec("DROP TABLE IF EXISTS bookings");
$pdo->exec("DROP TABLE IF EXISTS cars");
$pdo->exec("DROP TABLE IF EXISTS users");
$pdo->exec("SET FOREIGN_KEY_CHECKS=1");
echo "Existing tables dropped.\n";
// 1. Connect to Database Server
$pdo = db();
echo "<div class='step success'>✅ Connected to Database Server.</div>";
// 3. Create tables
// 2. Create Database (if it doesn't exist)
// Note: On some hosting/VMs, the user might not have permission to create databases, only tables.
// We try to create it if we are 'root' or similar, but otherwise assume it exists if connection worked.
$dbName = DB_NAME;
try {
$pdo->exec("CREATE DATABASE IF NOT EXISTS `$dbName` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
echo "<div class='step success'>✅ Database `$dbName` checked/created.</div>";
} catch (PDOException $e) {
// Ignore if we can't create DB (might already be connected to it)
echo "<div class='step'> Note: Could not create database (might already exist or permission denied). Proceeding...</div>";
}
// Select the database
$pdo->exec("USE `$dbName`");
// 3. Drop existing tables (Clean Install)
$pdo->exec("SET FOREIGN_KEY_CHECKS=0");
$tables = ['reviews', 'bookings', 'cars', 'users'];
foreach ($tables as $table) {
$pdo->exec("DROP TABLE IF EXISTS `$table`");
}
$pdo->exec("SET FOREIGN_KEY_CHECKS=1");
echo "<div class='step success'>✅ Existing tables dropped (Clean Install).</div>";
// 4. Create Tables
// Users Table
$pdo->exec(" CREATE TABLE users (
$pdo->exec("CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'user',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
echo "Users table ready.\n";
echo "<div class='step success'>✅ Table `users` created.</div>";
// Cars Table
$pdo->exec(" CREATE TABLE cars (
$pdo->exec("CREATE TABLE cars (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NULL,
title VARCHAR(255) NULL,
@ -52,10 +77,10 @@ try {
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
)");
echo "Cars table ready.\n";
echo "<div class='step success'>✅ Table `cars` created.</div>";
// Bookings Table
$pdo->exec(" CREATE TABLE bookings (
$pdo->exec("CREATE TABLE bookings (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
car_id INT NOT NULL,
@ -67,10 +92,10 @@ try {
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (car_id) REFERENCES cars(id) ON DELETE CASCADE
)");
echo "Bookings table ready.\n";
echo "<div class='step success'>✅ Table `bookings` created.</div>";
// Reviews Table
$pdo->exec(" CREATE TABLE reviews (
$pdo->exec("CREATE TABLE reviews (
id INT AUTO_INCREMENT PRIMARY KEY,
car_id INT NOT NULL,
user_id INT NOT NULL,
@ -81,30 +106,20 @@ try {
FOREIGN KEY (car_id) REFERENCES cars(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)");
echo "Reviews table ready.\n";
echo "<div class='step success'>✅ Table `reviews` created.</div>";
// 4. Add default admin user
$adminUsername = 'admin@gmail.com';
$adminPassword = '12345678';
$adminHash = password_hash($adminPassword, PASSWORD_DEFAULT);
// Check if admin exists (though we dropped tables, good practice)
$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE username = ?");
$stmt->execute([$adminUsername]);
if ($stmt->fetchColumn() == 0) {
$insertAdmin = $pdo->prepare("INSERT INTO users (username, password, role) VALUES (?, ?, 'admin')");
$insertAdmin->execute([$adminUsername, $adminHash]);
$adminId = $pdo->lastInsertId();
echo "Admin user created (User: $adminUsername, Pass: $adminPassword).\n";
} else {
echo "Admin user already exists.\n";
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
$stmt->execute([$adminUsername]);
$adminId = $stmt->fetchColumn();
}
// 5. Create Default Admin User
$adminUser = 'admin';
$adminEmail = 'admin@gmail.com';
$adminPass = '123'; // As requested
$adminHash = password_hash($adminPass, PASSWORD_DEFAULT);
// 5. Insert sample data (15 Cars)
$stmt = $pdo->prepare("INSERT INTO users (username, email, password, role) VALUES (?, ?, ?, 'admin')");
$stmt->execute([$adminUser, $adminEmail, $adminHash]);
$adminId = $pdo->lastInsertId();
echo "<div class='step success'>✅ Admin user created.<br> &nbsp;&nbsp; Username: <b>$adminUser</b><br> &nbsp;&nbsp; Email: <b>$adminEmail</b><br> &nbsp;&nbsp; Password: <b>$adminPass</b></div>";
// 6. Insert Sample Data (Cars)
$carsData = [
[
'title' => 'Toyota Corolla 2020 Clean',
@ -286,7 +301,7 @@ try {
'color' => 'Red',
'province' => 'Mazar-i-Sharif',
'city' => 'Mazar',
'image_url' => 'https://images.pexels.com/photos/35967/mini-cooper-auto-model-vehicle.jpg?auto=compress&cs=tinysrgb&w=600' // Placeholder for small car
'image_url' => 'https://images.pexels.com/photos/35967/mini-cooper-auto-model-vehicle.jpg?auto=compress&cs=tinysrgb&w=600'
],
[
'title' => 'Mazda 6 2019',
@ -324,10 +339,14 @@ try {
$car['user_id'] = $adminId;
$insertCar->execute($car);
}
echo "Seed data inserted (" . count($carsData) . " cars).\n";
echo "<div class='step success'>✅ Seed data inserted (" . count($carsData) . " cars).</div>";
echo "Setup complete. The application is ready to use.\n";
echo "<hr><h2>🎉 Installation Complete!</h2>";
echo "<p>You can now <a href='login.php'>Login here</a>.</p>";
echo "<p><b>Credentials:</b><br>Username: <code>admin</code> or <code>admin@gmail.com</code><br>Password: <code>123</code></p>";
} catch (PDOException $e) {
die("Setup failed: " . $e->getMessage() . "\n");
}
echo "<div class='step error'>❌ Installation Failed: " . htmlspecialchars($e->getMessage()) . "</div>";
}
echo "</body></html>";
?>

View File

@ -14,12 +14,14 @@ if (isset($_SESSION['user_id'])) {
}
$errors = [];
$login_input = ''; // Store input to repopulate form
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$login_input = trim($_POST['username'] ?? ''); // This field now accepts user OR email
$password = $_POST['password'] ?? '';
if (empty($username)) {
$errors[] = 'Username is required.';
if (empty($login_input)) {
$errors[] = 'Username or Email is required.';
}
if (empty($password)) {
$errors[] = 'Password is required.';
@ -28,20 +30,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (empty($errors)) {
try {
$pdo = db();
// Allow login by username only per new schema
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username LIMIT 1");
$stmt->execute(['username' => $username]);
// Allow login by username OR email
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = :input OR email = :input LIMIT 1");
$stmt->execute(['input' => $login_input]);
$user = $stmt->fetch();
// Note: The 'password' column stores the hash
if ($user && password_verify($password, $user['password'])) {
if (isset($user['status']) && $user['status'] !== 'active') {
// Kept specific status check logic if status column existed, but since schema is simple, this block is mostly for safety if schema evolves.
// Current schema doesn't have status, but if it did, we'd check it.
// The setup_project.php removed the status column from users table to fit the simple requirements.
// So we proceed.
}
// Login Success
$_SESSION['user_id'] = $user['id'];
$_SESSION['username'] = $user['username'];
$_SESSION['role'] = $user['role'];
@ -94,7 +90,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<form action="login.php" method="POST">
<div class="mb-4">
<label for="username" class="form-label fw-semibold">Username or Email</label>
<input type="text" id="username" name="username" class="form-control form-control-lg" placeholder="admin@gmail.com" required value="<?php echo isset($username) ? htmlspecialchars($username) : ''; ?>">
<input type="text" id="username" name="username" class="form-control form-control-lg" placeholder="admin or admin@gmail.com" required value="<?php echo htmlspecialchars($login_input); ?>">
</div>
<div class="mb-4">
<label for="password" class="form-label fw-semibold">Password</label>

View File

@ -9,14 +9,23 @@ if (isset($_SESSION['user_id'])) {
}
$errors = [];
$username = '';
$email = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$username = trim($_POST['username'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
// Validation
if (empty($username)) {
$errors[] = 'Username is required.';
}
if (empty($email)) {
$errors[] = 'Email is required.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$errors[] = 'Invalid email format.';
}
if (empty($password)) {
$errors[] = 'Password is required.';
} elseif (strlen($password) < 8) {
@ -26,18 +35,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (empty($errors)) {
try {
$pdo = db();
// Check if username already exists
$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE username = :username");
$stmt->execute(['username' => $username]);
// Check if username OR email already exists
$stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE username = :username OR email = :email");
$stmt->execute(['username' => $username, 'email' => $email]);
if ($stmt->fetchColumn() > 0) {
$errors[] = 'Username is already taken.';
// Determine which one exists for better error message (optional but nice)
// For simplicity:
$errors[] = 'Username or Email is already taken.';
} else {
// Hash password and insert new user
$password_hash = password_hash($password, PASSWORD_DEFAULT);
// Schema: id, username, password, role, created_at
$insert_stmt = $pdo->prepare("INSERT INTO users (username, password, role) VALUES (:username, :password, 'user')");
// Schema: id, username, email, password, role, created_at
$insert_stmt = $pdo->prepare("INSERT INTO users (username, email, password, role) VALUES (:username, :email, :password, 'user')");
$insert_stmt->execute([
':username' => $username,
':email' => $email,
':password' => $password_hash
]);
@ -85,7 +97,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<form action="register.php" method="POST">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="e.g., ahmadwali" required value="<?php echo isset($username) ? htmlspecialchars($username) : ''; ?>">
<input type="text" id="username" name="username" class="form-control" placeholder="e.g., ahmadwali" required value="<?php echo htmlspecialchars($username); ?>">
</div>
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<input type="email" id="email" name="email" class="form-control" placeholder="e.g., ahmad@example.com" required value="<?php echo htmlspecialchars($email); ?>">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>