= 7.4' => version_compare(PHP_VERSION, '7.4.0', '>='), 'PDO Extension' => extension_loaded('pdo'), 'PDO MySQL Extension' => extension_loaded('pdo_mysql'), 'Config Directory Writable' => is_writable(__DIR__ . '/db/'), 'Uploads Directory Writable' => is_writable(__DIR__ . '/uploads/') || (mkdir(__DIR__ . '/uploads/', 0777, true) && is_writable(__DIR__ . '/uploads/')), ]; $all_requirements_met = !in_array(false, $requirements, true); // Current step $step = isset($_GET['step']) ? (int)$_GET['step'] : 1; // Handle form submissions $error = ''; $success = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($step === 2) { // Save database configuration $host = $_POST['db_host'] ?? '127.0.0.1'; $name = $_POST['db_name'] ?? 'app_database'; $user = $_POST['db_user'] ?? 'root'; $pass = $_POST['db_pass'] ?? ''; // Test connection try { $test_pdo = new PDO("mysql:host=$host;dbname=$name;charset=utf8mb4", $user, $pass); $test_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Generate config file content $content = "setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\n"; $content .= " \$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);\n"; $content .= " } catch (PDOException \$e) {\n"; $content .= " die('Connection failed: ' . \$e->getMessage());\n"; $content .= " }\n"; $content .= " }\n"; $content .= " return \$pdo;\n"; $content .= " }\n"; $content .= "}\n"; if (file_put_contents($config_file, $content)) { header('Location: install.php?step=3'); exit; } else { $error = "Failed to write configuration file to $config_file. Please check permissions."; } } catch (PDOException $e) { $error = "Connection failed: " . $e->getMessage(); } } elseif ($step === 3) { // Run migrations if (!file_exists($config_file)) { $error = "Configuration file not found. Please go back to Step 2."; } else { try { require_once $config_file; if (!function_exists('db')) { throw new Exception("The 'db()' function is not defined in your config file."); } $pdo = db(); $migrations_dir = __DIR__ . '/db/migrations/'; $files = glob($migrations_dir . '*.sql'); if ($files === false) $files = []; sort($files); $applied = 0; $errors = []; foreach ($files as $file) { $sql = file_get_contents($file); if (empty($sql)) continue; try { // Split SQL into multiple statements if necessary // Simple split by semicolon. This might fail on some complex SQL, // but usually works for basic migrations. $statements = array_filter(array_map('trim', explode(';', $sql))); foreach ($statements as $stmt_sql) { if (empty($stmt_sql)) continue; try { $pdo->exec($stmt_sql); } catch (Throwable $e) { $msg = $e->getMessage(); // Check if it's a common "already exists" error which we can safely ignore if (strpos($msg, 'Duplicate column name') !== false || strpos($msg, 'Duplicate key name') !== false || strpos($msg, 'Duplicate table') !== false || strpos($msg, 'already exists') !== false) { continue; } else { throw $e; } } } $applied++; } catch (Throwable $e) { $errors[] = basename($file) . ": " . $e->getMessage(); } } if (empty($errors)) { $success = "Successfully applied $applied migrations."; header('Location: install.php?step=4'); exit; } else { $error = "Applied migrations, but some errors occurred:
"; } } catch (Throwable $e) { $error = "Migration failed: " . $e->getMessage(); } } } elseif ($step === 4) { // Final setup (Admin account) require_once $config_file; $pdo = db(); $admin_user = $_POST['admin_user'] ?? 'admin'; $admin_pass = $_POST['admin_pass'] ?? ''; $admin_email = $_POST['admin_email'] ?? 'admin@example.com'; if (strlen($admin_pass) < 6) { $error = "Password must be at least 6 characters long."; } else { try { $hashed_pass = password_hash($admin_pass, PASSWORD_DEFAULT); $stmt = $pdo->prepare("INSERT INTO users (username, password, email, role) VALUES (?, ?, ?, 'admin') ON DUPLICATE KEY UPDATE password = ?, email = ?"); $stmt->execute([$admin_user, $hashed_pass, $admin_email, $hashed_pass, $admin_email]); // Set initial settings $pdo->exec("INSERT IGNORE INTO charity_settings (id, charity_name) VALUES (1, 'Admin Panel')"); $pdo->exec("INSERT IGNORE INTO smtp_settings (id, is_enabled) VALUES (1, 0)"); header('Location: install.php?step=5'); exit; } catch (Throwable $e) { $error = "Failed to create admin account: " . $e->getMessage(); } } } } // UI Template ?> Installer - Step <?= $step ?>

Installer

$i\n"; endfor; ?>

Step 1: System Requirements

    $met): echo "
  • "; echo "$name\n"; if ($met) { echo "OK"; } else { echo "Failed"; } echo "
  • \n"; endforeach; ?>
Next: Database Config Fix requirements to continue"; endif; ?>

Step 2: Database Connection

Step 3: Database Migrations

We will now run the SQL scripts to set up your database tables.

Step 4: Admin Account

Installation Complete!

The system is ready to use. For security, please delete install.php or rename it.