update setting

This commit is contained in:
Flatlogic Bot 2026-05-09 14:12:41 +00:00
parent 8896b8d05a
commit 969ead5890
2 changed files with 111 additions and 19 deletions

View File

@ -278,9 +278,13 @@ class DatabaseInstaller {
private static function splitSqlStatements(string $sql): array {
$sql = preg_replace('/^\xEF\xBB\xBF/', '', $sql) ?? $sql;
$sql = preg_replace('/\/\*.*?\*\//s', '', $sql) ?? $sql;
$sql = preg_replace('/\/\*!\d+\s*(.*?)\*\//s', '$1', $sql) ?? $sql;
$sql = preg_replace('/\/\*(?!\!)(.*?)\*\//s', '', $sql) ?? $sql;
$sql = str_replace(["\r\n", "\r"], "\n", $sql);
$lines = preg_split('/\R/', $sql) ?: [];
// Do not use \R here. In byte mode it treats 0x85 as a newline,
// which corrupts UTF-8 Arabic seed data (for example حرف م = 0xD9 0x85).
$lines = explode("\n", $sql);
$filteredLines = [];
foreach ($lines as $line) {

View File

@ -45,6 +45,69 @@ function installationMigrationFiles(): array {
return $files;
}
function installationBuildDsn(string $host, ?string $dbName = null): string {
$normalizedHost = trim($host);
$port = null;
if (substr_count($normalizedHost, ':') === 1) {
[$hostPart, $portPart] = explode(':', $normalizedHost, 2);
if ($hostPart !== '' && ctype_digit($portPart)) {
$normalizedHost = $hostPart;
$port = $portPart;
}
}
$dsn = 'mysql:host=' . $normalizedHost;
if ($port !== null) {
$dsn .= ';port=' . $port;
}
if ($dbName !== null && $dbName !== '') {
$dsn .= ';dbname=' . $dbName;
}
return $dsn . ';charset=utf8mb4';
}
function installationQuoteIdentifier(string $identifier): string {
return '`' . str_replace('`', '``', $identifier) . '`';
}
function installationBuildConfigContent(string $host, string $name, string $user, string $pass): string {
return sprintf(
<<<'PHP'
<?php
define('DB_HOST', %s);
define('DB_NAME', %s);
define('DB_USER', %s);
define('DB_PASS', %s);
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,
]);
if (session_status() === PHP_SESSION_NONE && !headers_sent()) {
@session_start();
}
if (isset($_SESSION['outlet_id'])) {
$pdo->exec("SET @session_outlet_id = " . (int)$_SESSION['outlet_id']);
} else {
$pdo->exec("SET @session_outlet_id = 0");
}
}
return $pdo;
}
PHP,
var_export($host, true),
var_export($name, true),
var_export($user, true),
var_export($pass, true)
);
}
// Step 1: Requirements
if ($step === 1) {
$requirements = [
@ -82,22 +145,41 @@ if ($step === 1) {
// 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'] ?? '';
$host = trim((string) ($_POST['db_host'] ?? ''));
$name = trim((string) ($_POST['db_name'] ?? ''));
$user = trim((string) ($_POST['db_user'] ?? ''));
$pass = (string) ($_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 = "<?php\ndefine('DB_HOST', '$host');\ndefine('DB_NAME', '$name');\ndefine('DB_USER', '$user');\ndefine('DB_PASS', '$pass');\n\nfunction 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: index.php?step=3");
exit;
} catch (PDOException $e) {
$error = "Database Connection Failed: " . $e->getMessage();
if ($host === '' || $name === '' || $user === '') {
$error = 'Database host, name, and user are required.';
} else {
try {
$pdoOptions = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$pdo = new PDO(installationBuildDsn($host, $name), $user, $pass, $pdoOptions);
} catch (PDOException $connectionException) {
$pdo = new PDO(installationBuildDsn($host), $user, $pass, $pdoOptions);
$pdo->exec('CREATE DATABASE IF NOT EXISTS ' . installationQuoteIdentifier($name) . ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci');
}
$configPath = __DIR__ . '/../db/config.php';
$bytesWritten = file_put_contents($configPath, installationBuildConfigContent($host, $name, $user, $pass));
if ($bytesWritten === false) {
throw new RuntimeException('Unable to write db/config.php');
}
require_once __DIR__ . '/../includes/DatabaseInstaller.php';
DatabaseInstaller::install();
header("Location: index.php?step=3");
exit;
} catch (Throwable $e) {
$error = "Database Setup Failed: " . $e->getMessage();
}
}
}
@ -110,7 +192,11 @@ if ($step === 3 && $_SERVER['REQUEST_METHOD'] === 'POST') {
try {
require_once __DIR__ . '/../includes/DatabaseInstaller.php';
DatabaseInstaller::install();
if (!DatabaseInstaller::isInstalled()) {
DatabaseInstaller::install();
} else {
DatabaseInstaller::ensureCurrentSchema();
}
$pdo = db();
// Ensure Admin Role exists (might be in schema but just in case)
@ -160,6 +246,7 @@ if ($step === 4) {
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex, nofollow">
<title>Installation - Step <?= $step ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
@ -247,9 +334,10 @@ if ($step === 4) {
<input type="password" name="db_pass" class="form-control" placeholder="Enter password">
</div>
<div class="d-grid mt-4">
<button type="submit" class="btn btn-primary">Verify & Save Config</button>
<button type="submit" class="btn btn-primary">Verify, Save & Import Schema</button>
</div>
</form>
<div class="alert alert-info small mt-3 mb-0">This step creates the database tables and imports the base schema before you add the admin account.</div>
<?php elseif ($step === 3): ?>
<h5 class="fw-bold mb-4">Step 3: Super Admin Setup</h5>