exec($query); } catch (PDOException $e) { $msg = $e->getMessage(); if ( strpos($msg, 'already exists') !== false || strpos($msg, 'Duplicate column name') !== false || strpos($msg, 'Duplicate key name') !== false || strpos($msg, 'Duplicate entry') !== false || strpos($msg, "Can't DROP") !== false || strpos($msg, "Cannot drop index") !== false || strpos($msg, "needed in a foreign key constraint") !== false || strpos($msg, 'check that column/key exists') !== false || strpos($msg, 'Unknown table') !== false ) { continue; } throw $e; } } } return true; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($step === 2) { $host = $_POST['db_host'] ?? '127.0.0.1'; $user = $_POST['db_user'] ?? ''; $pass = $_POST['db_pass'] ?? ''; $name = $_POST['db_name'] ?? ''; try { $pdo = new PDO("mysql:host=$host;charset=utf8mb4", $user, $pass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->exec("CREATE DATABASE IF NOT EXISTS `$name` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci"); $pdo->exec("USE `$name` "); // Read existing helpers from current config if it exists $helpers = ''; if (file_exists(__DIR__ . '/db/config.php')) { $currentConfig = file_get_contents(__DIR__ . '/db/config.php'); // Extract functions after the db() function or constants if (preg_match('/function check_permission.*$/s', $currentConfig, $matches)) { $helpers = $matches[0]; } } // If helpers weren't found, use a set of default ones if (empty($helpers)) { $helpers = " function check_permission(\$page = null, \$user_id = null) { if (!\$user_id) \$user_id = eg_SESSION['user_id'] ?? null; if (!\$page) \$page = basename( eg_SERVER['PHP_SELF']); if (!\$user_id) return ['view' => 0, 'add' => 0, 'edit' => 0, 'delete' => 0]; static \$permissions_cache = []; \$cache_key = \$user_id . '_' . \$page; if (isset( eg_permissions_cache[\$cache_key])) return \$permissions_cache[\$cache_key]; \$stmt = db()->prepare(\"SELECT can_view as view, can_add as `add`, can_edit as edit, can_delete as `delete` FROM user_permissions WHERE user_id = ? AND page = ?\"); \$stmt->execute([\$user_id, \$page]); \$perms = \$stmt->fetch(); if (!\$perms) return ['view' => 0, 'add' => 0, 'edit' => 0, 'delete' => 0]; \$result = ['view' => (int) eg_perms['view'], 'add' => (int) eg_perms['add'], 'edit' => (int) eg_perms['edit'], 'delete' => (int) eg_perms['delete']]; \$permissions_cache[\$cache_key] = \$result; return \$result; } function has_permission(\$action, \$page = null, \$user_id = null) { \$perms = check_permission( eg_page, \$user_id); return !empty( eg_perms[\$action]); }"; } $configContent = " PDO::ERRMODE_EXCEPTION,\n" . " PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,\n" . " PDO::ATTR_EMULATE_PREPARES => false,\n" . " ]);\n" . " }\n" . " return \$pdo;\n" . "}\n\n" . trim($helpers) . "\n"; if (!is_dir(__DIR__ . '/db')) mkdir(__DIR__ . '/db', 0755, true); file_put_contents(__DIR__ . '/db/config.php', $configContent); // Run initial schema $pdo->exec("SET FOREIGN_KEY_CHECKS = 0;"); $migrations = glob(__DIR__ . "/db/migrations/*.sql"); sort($migrations); foreach ($migrations as $migration) { runSqlFile($pdo, $migration); } $pdo->exec("SET FOREIGN_KEY_CHECKS = 1;"); $_SESSION['db_configured'] = true; header("Location: install.php?step=3"); exit; } catch (PDOException $e) { $error = "Connection failed: " . $e->getMessage(); } } elseif ($step === 3) { require_once __DIR__ . '/db/config.php'; $user = $_POST['admin_user'] ?? ''; $pass = $_POST['admin_pass'] ?? ''; $email = $_POST['admin_email'] ?? ''; if (empty($user) || empty($pass)) { $error = "Username and password are required."; } else { try { $hash = password_hash($pass, PASSWORD_DEFAULT); $db = db(); // Clear existing users $db->exec("SET FOREIGN_KEY_CHECKS = 0;"); $db->exec("TRUNCATE users;"); $db->exec("SET FOREIGN_KEY_CHECKS = 1;"); // Ensure company and branch exist (schema usually seeds them, but we ensure) $db->exec("INSERT IGNORE INTO companies (id, name_en, name_ar) VALUES (1, 'Laundry Brand', 'علامة غسيل')"); $db->exec("INSERT IGNORE INTO branches (id, company_id, name_en, name_ar) VALUES (1, 1, 'Main Branch', 'الفرع الرئيسي')"); $stmt = $db->prepare("INSERT INTO users (branch_id, company_id, username, password_hash, full_name_en, role, email) VALUES (1, 1, ?, ?, 'System Administrator', 'super_admin', ?)"); $stmt->execute([$user, $hash, $email]); file_put_contents($lockFile, date('Y-m-d H:i:s')); header("Location: install.php?step=4"); exit; } catch (Exception $e) { $error = "Admin setup failed: " . $e->getMessage(); } } } } // Environment Checks $checks = [ 'PHP Version >= 8.0' => version_compare(PHP_VERSION, '8.0.0', '>='), 'PDO Extension' => extension_loaded('pdo_mysql'), 'Config Writable' => is_writable(__DIR__ . '/db/config.php') || is_writable(__DIR__), 'Assets Writable' => (is_writable(__DIR__ . '/assets/images') || (is_dir(__DIR__ . '/assets/images') && is_writable(__DIR__ . '/assets/images'))) ]; $envReady = !in_array(false, $checks, true); ?> Fresh Installation

Setup Wizard

Step-by-step application installation

1
2
3
4
Checking Environment
$pass): ?>
Passed Failed
Continue to Database
Database Configuration
Administrator Account
Installation Complete!

The application has been configured and the administrator account is ready.

Login to System

Warning: Delete install.php for production security.