39414-vm/install.php
2026-04-01 09:16:10 +00:00

213 lines
12 KiB
PHP

<?php
declare(strict_types=1);
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
if (file_exists(__DIR__ . '/.installed') || file_exists(__DIR__ . '/install.lock')) {
die('Installation already completed. To reinstall, delete the .installed file.');
}
$step = isset($_GET['step']) ? (int)$_GET['step'] : 1;
$error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$step = isset($_POST['step']) ? (int)$_POST['step'] : $step;
if ($step === 3) {
$dbHost = $_POST['db_host'] ?? '';
$dbName = $_POST['db_name'] ?? '';
$dbUser = $_POST['db_user'] ?? '';
$dbPass = $_POST['db_pass'] ?? '';
try {
$pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
// Rewrite db/config.php
$configContent = "<?php\n" .
"define('DB_HOST', '$dbHost');\n" .
"define('DB_NAME', '$dbName');\n" .
"define('DB_USER', '$dbUser');\n" .
"define('DB_PASS', '$dbPass');\n\n" .
"function db() {\n" .
" static \$pdo;\n" .
" if (!\$pdo) {\n" .
" \$pdo = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4', DB_USER, DB_PASS, [\n" .
" PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,\n" .
" PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,\n" .
" ]);\n" .
" }\n" .
" return \$pdo;\n" .
"}\n";
file_put_contents(__DIR__ . '/db/config.php', $configContent);
header('Location: install.php?step=4');
exit;
} catch (Exception $e) {
$error = 'Database Connection Failed: ' . $e->getMessage();
}
} elseif ($step === 4) {
require_once __DIR__ . '/db/config.php';
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
if (empty($username) || empty($password)) {
$error = 'Please provide both username and password.';
} else {
try {
$pdo = db();
$pdo->exec("CREATE TABLE IF NOT EXISTS users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
$hash = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (username, password) VALUES (:username, :password) ON DUPLICATE KEY UPDATE password = :password");
$stmt->execute(['username' => $username, 'password' => $hash]);
header('Location: install.php?step=5');
exit;
} catch (Exception $e) {
$error = 'Failed to create user: ' . $e->getMessage();
}
}
} elseif ($step === 5) {
file_put_contents(__DIR__ . '/.installed', date('Y-m-d H:i:s'));
file_put_contents(__DIR__ . '/install.lock', date('Y-m-d H:i:s'));
header('Location: login.php');
exit;
}
}
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Installation</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body { background-color: #f8f9fa; }
.install-card { border: none; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }
</style>
</head>
<body>
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-md-8 col-lg-6">
<div class="card install-card">
<div class="card-header bg-white border-bottom-0 pt-4 pb-0">
<h3 class="card-title text-center text-primary mb-0 fw-bold">System Installation</h3>
<div class="text-center text-muted mt-2">Step <?= $step ?> of 5</div>
</div>
<div class="card-body p-4">
<?php if ($error): ?>
<div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
<?php endif; ?>
<?php if ($step === 1): ?>
<h4 class="mb-3 text-dark">Welcome</h4>
<p class="text-secondary">Welcome to the Hospital Queue Center installation wizard. This will set up your environment, configure the database variables, and create your super admin account so you are ready to go.</p>
<div class="text-end mt-4">
<a href="install.php?step=2" class="btn btn-primary px-4 py-2 rounded-pill">Next: Environment Check</a>
</div>
<?php elseif ($step === 2): ?>
<h4 class="mb-3 text-dark">Environment Check</h4>
<ul class="list-group mb-4 rounded-3">
<?php
$phpOk = version_compare(PHP_VERSION, '8.0.0', '>=');
$pdoOk = extension_loaded('pdo_mysql');
$dbWritable = is_writable(__DIR__ . '/db') || is_writable(__DIR__ . '/db/config.php');
?>
<li class="list-group-item d-flex justify-content-between align-items-center">
PHP Version (>= 8.0)
<span class="badge bg-<?= $phpOk ? 'success' : 'danger' ?> rounded-pill px-3 py-2"><?= PHP_VERSION ?></span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
PDO MySQL Extension
<span class="badge bg-<?= $pdoOk ? 'success' : 'danger' ?> rounded-pill px-3 py-2"><?= $pdoOk ? 'Yes' : 'No' ?></span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
DB Config Writable
<span class="badge bg-<?= $dbWritable ? 'success' : 'danger' ?> rounded-pill px-3 py-2"><?= $dbWritable ? 'Yes' : 'No' ?></span>
</li>
</ul>
<?php if ($phpOk && $pdoOk && $dbWritable): ?>
<div class="text-end">
<a href="install.php?step=3" class="btn btn-primary px-4 py-2 rounded-pill">Next: Database Variables</a>
</div>
<?php else: ?>
<div class="alert alert-warning">Please fix the environment issues before proceeding.</div>
<?php endif; ?>
<?php elseif ($step === 3): ?>
<h4 class="mb-3 text-dark">Database Variables</h4>
<?php
$dbHost = defined('DB_HOST') ? DB_HOST : '127.0.0.1';
$dbName = defined('DB_NAME') ? DB_NAME : '';
$dbUser = defined('DB_USER') ? DB_USER : '';
$dbPass = defined('DB_PASS') ? DB_PASS : '';
if (file_exists(__DIR__ . '/db/config.php')) {
$content = file_get_contents(__DIR__ . '/db/config.php');
if (preg_match("/define\('DB_HOST',\s*'([^']+)'\)/", $content, $m)) $dbHost = $m[1];
if (preg_match("/define\('DB_NAME',\s*'([^']+)'\)/", $content, $m)) $dbName = $m[1];
if (preg_match("/define\('DB_USER',\s*'([^']+)'\)/", $content, $m)) $dbUser = $m[1];
if (preg_match("/define\('DB_PASS',\s*'([^']+)'\)/", $content, $m)) $dbPass = $m[1];
}
?>
<form method="POST" action="install.php">
<input type="hidden" name="step" value="3">
<div class="mb-3">
<label class="form-label text-secondary fw-semibold">Database Host</label>
<input type="text" name="db_host" class="form-control form-control-lg bg-light" value="<?= htmlspecialchars($dbHost) ?>" required>
</div>
<div class="mb-3">
<label class="form-label text-secondary fw-semibold">Database Name</label>
<input type="text" name="db_name" class="form-control form-control-lg bg-light" value="<?= htmlspecialchars($dbName) ?>" required>
</div>
<div class="mb-3">
<label class="form-label text-secondary fw-semibold">Database User</label>
<input type="text" name="db_user" class="form-control form-control-lg bg-light" value="<?= htmlspecialchars($dbUser) ?>" required>
</div>
<div class="mb-3">
<label class="form-label text-secondary fw-semibold">Database Password</label>
<input type="password" name="db_pass" class="form-control form-control-lg bg-light" value="<?= htmlspecialchars($dbPass) ?>" required>
</div>
<div class="text-end mt-4">
<button type="submit" class="btn btn-primary px-4 py-2 rounded-pill">Save & Next</button>
</div>
</form>
<?php elseif ($step === 4): ?>
<h4 class="mb-3 text-dark">Super Admin Credentials</h4>
<form method="POST" action="install.php">
<input type="hidden" name="step" value="4">
<div class="mb-3">
<label class="form-label text-secondary fw-semibold">Admin Username</label>
<input type="text" name="username" class="form-control form-control-lg bg-light" value="admin" required>
</div>
<div class="mb-3">
<label class="form-label text-secondary fw-semibold">Admin Password</label>
<input type="password" name="password" class="form-control form-control-lg bg-light" required>
</div>
<div class="text-end mt-4">
<button type="submit" class="btn btn-primary px-4 py-2 rounded-pill">Create Admin & Next</button>
</div>
</form>
<?php elseif ($step === 5): ?>
<h4 class="mb-3 text-success fw-bold">Ready to go!</h4>
<p class="text-secondary mb-4">The installation has been successfully completed. Your database is set up and the super admin account is ready.</p>
<form method="POST" action="install.php">
<input type="hidden" name="step" value="5">
<button type="submit" class="btn btn-success w-100 py-3 rounded-pill fw-bold" style="font-size: 1.1rem;">Finish & Go to Login</button>
</form>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
</body>
</html>