'20260318_10_add_outlet_id_to_purchases.sql', '20260318_create_outlets_table.sql' => '20260318_20_create_outlets_table.sql', '20260318_multi_outlet_schema.sql' => '20260318_30_multi_outlet_schema.sql', '20260318_local_definitions.sql' => '20260318_40_local_definitions.sql', '20260318_user_outlets_table.sql' => '20260318_50_user_outlets_table.sql', default => $basename, }; } function installationLegacyNumberedMigrationFile(string $filePath): bool { // Skip obsolete pre-date-based migrations from older packaged builds. return preg_match('/^\d{1,7}_/', basename($filePath)) === 1; } function installationMigrationFiles(): array { $files = array_merge( glob(__DIR__ . '/../db/migrations/*.sql') ?: [], glob(__DIR__ . '/../db/migrations/*.php') ?: [] ); $files = array_values(array_filter($files, static function (string $filePath): bool { return !installationLegacyNumberedMigrationFile($filePath); })); usort($files, static function (string $left, string $right): int { return strnatcasecmp(installationMigrationSortKey($left), installationMigrationSortKey($right)); }); return $files; } // Step 1: Requirements if ($step === 1) { $requirements = [ 'php_version' => [ 'name' => 'PHP Version (>= 8.0)', 'status' => version_compare(PHP_VERSION, '8.0.0', '>='), 'current' => PHP_VERSION ], 'pdo_mysql' => [ 'name' => 'PDO MySQL Extension', 'status' => extension_loaded('pdo_mysql'), 'current' => extension_loaded('pdo_mysql') ? 'Loaded' : 'Missing' ], 'curl' => [ 'name' => 'cURL Extension (Required for Licensing)', 'status' => extension_loaded('curl'), 'current' => extension_loaded('curl') ? 'Loaded' : 'Missing' ], 'config_writable' => [ 'name' => 'db/config.php Writable', 'status' => is_writable(__DIR__ . '/../db/config.php'), 'current' => is_writable(__DIR__ . '/../db/config.php') ? 'Yes' : 'No' ], 'root_writable' => [ 'name' => 'Root Directory Writable', 'status' => is_writable(__DIR__ . '/..'), 'current' => is_writable(__DIR__ . '/..') ? 'Yes' : 'No' ] ]; $allOk = true; foreach ($requirements as $req) { if (!$req['status']) $allOk = false; } } // Step 2: Database if ($step === 2 && $_SERVER['REQUEST_METHOD'] === 'POST') { $host = $_POST['db_host'] ?? ''; $name = $_POST['db_name'] ?? ''; $user = $_POST['db_user'] ?? ''; $pass = $_POST['db_pass'] ?? ''; try { $pdo = new PDO("mysql:host=$host;dbname=$name", $user, $pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]); // Save to config.php $configContent = " 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: index.php?step=3"); exit; } catch (PDOException $e) { $error = "Database Connection Failed: " . $e->getMessage(); } } // Step 3: Super Admin if ($step === 3 && $_SERVER['REQUEST_METHOD'] === 'POST') { require_once __DIR__ . '/../db/config.php'; $adminUser = $_POST['admin_user'] ?? ''; $adminPass = $_POST['admin_pass'] ?? ''; $adminEmail = $_POST['admin_email'] ?? ''; try { require_once __DIR__ . '/../includes/DatabaseInstaller.php'; DatabaseInstaller::install(); $pdo = db(); // Ensure Admin Role exists (might be in schema but just in case) $stmt = $pdo->prepare("SELECT id FROM role_groups WHERE name = 'Administrator'"); $stmt->execute(); $role = $stmt->fetch(); if (!$role) { $pdo->exec("INSERT INTO role_groups (name) VALUES ('Administrator')"); $roleId = $pdo->lastInsertId(); $pdo->exec("INSERT INTO role_permissions (role_id, permission) VALUES ($roleId, 'all')"); } else { $roleId = $role['id']; // Also ensure 'all' permission exists for it $stmt = $pdo->prepare("SELECT id FROM role_permissions WHERE role_id = ? AND permission = 'all'"); $stmt->execute([$roleId]); if (!$stmt->fetch()) { $pdo->exec("INSERT INTO role_permissions (role_id, permission) VALUES ($roleId, 'all')"); } } // Insert Admin User (Use ON DUPLICATE KEY UPDATE to handle existing user from schema) $hashedPass = password_hash($adminPass, PASSWORD_DEFAULT); $stmt = $pdo->prepare("INSERT INTO users (username, password, email, group_id, status) VALUES (?, ?, ?, ?, 'active') ON DUPLICATE KEY UPDATE password = VALUES(password), email = VALUES(email), group_id = VALUES(group_id), status = 'active'"); $stmt->execute([$adminUser, $hashedPass, $adminEmail, $roleId]); header("Location: index.php?step=4"); exit; } catch (Exception $e) { $error = "Setup Failed: " . $e->getMessage(); } } // Step 4: Finish if ($step === 4) { file_put_contents($lockFile, date('Y-m-d H:i:s')); } ?>
Configure your application in minutes
Installation completed successfully. Your system is now secure and ready to use.
installed.lock file has been created.