Update InstallerController.php
This commit is contained in:
@@ -55,7 +55,8 @@ class InstallerController extends Controller
|
|||||||
try {
|
try {
|
||||||
$pdo = \Core\Database::getConnection();
|
$pdo = \Core\Database::getConnection();
|
||||||
|
|
||||||
// First, check if this is a fresh install by looking for any existing tables
|
// First, check if this is a fresh install by looking for core application tables
|
||||||
|
// Core tables that indicate a real installation: users, domains, settings, notification_groups
|
||||||
$hasUsers = false;
|
$hasUsers = false;
|
||||||
$hasDomains = false;
|
$hasDomains = false;
|
||||||
$hasSettings = false;
|
$hasSettings = false;
|
||||||
@@ -97,11 +98,30 @@ class InstallerController extends Controller
|
|||||||
// Migrations table doesn't exist
|
// Migrations table doesn't exist
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no tables exist at all - this is a fresh install
|
// If no core application tables exist - this is a fresh install
|
||||||
if (!$hasUsers && !$hasDomains && !$hasSettings && !$hasNotificationGroups && !$hasMigrations) {
|
// Core tables are: users, domains, settings, notification_groups
|
||||||
|
// Note: sessions, password_reset_tokens, etc. might exist from app startup but don't indicate real installation
|
||||||
|
if (!$hasUsers && !$hasDomains && !$hasSettings && !$hasNotificationGroups) {
|
||||||
return $freshInstallMigration;
|
return $freshInstallMigration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Additional check: if we have some tables but no actual data in core tables, treat as fresh install
|
||||||
|
// This handles cases where tables might be created by app startup but no real data exists
|
||||||
|
if ($hasUsers && !$hasDomains && !$hasSettings && !$hasNotificationGroups) {
|
||||||
|
// Only users table exists, check if it has any real data
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->query("SELECT COUNT(*) FROM users WHERE role = 'admin'");
|
||||||
|
$adminCount = $stmt->fetchColumn();
|
||||||
|
if ($adminCount == 0) {
|
||||||
|
// No admin users, treat as fresh install
|
||||||
|
return $freshInstallMigration;
|
||||||
|
}
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
// Error checking users, treat as fresh install
|
||||||
|
return $freshInstallMigration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create migrations table if it doesn't exist
|
// Create migrations table if it doesn't exist
|
||||||
$pdo->exec("
|
$pdo->exec("
|
||||||
CREATE TABLE IF NOT EXISTS migrations (
|
CREATE TABLE IF NOT EXISTS migrations (
|
||||||
@@ -278,17 +298,25 @@ class InstallerController extends Controller
|
|||||||
$sql = str_replace('{{ADMIN_EMAIL}}', $adminEmail, $sql);
|
$sql = str_replace('{{ADMIN_EMAIL}}', $adminEmail, $sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute SQL
|
// Execute SQL - use a more robust method for complex SQL files
|
||||||
$statements = array_filter(array_map('trim', explode(';', $sql)));
|
try {
|
||||||
|
// For complex migration files, execute the entire SQL at once
|
||||||
|
// This handles multi-line statements, comments, and complex syntax properly
|
||||||
|
$pdo->exec($sql);
|
||||||
|
} catch (\PDOException $e) {
|
||||||
|
// If that fails, try the statement-by-statement approach as fallback
|
||||||
|
$statements = $this->parseSqlStatements($sql);
|
||||||
foreach ($statements as $statement) {
|
foreach ($statements as $statement) {
|
||||||
if (!empty($statement)) {
|
if (!empty(trim($statement))) {
|
||||||
try {
|
try {
|
||||||
$pdo->exec($statement);
|
$pdo->exec($statement);
|
||||||
} catch (\PDOException $e) {
|
} catch (\PDOException $e2) {
|
||||||
// Ignore duplicate/already exists errors
|
// Ignore duplicate/already exists errors
|
||||||
if (strpos($e->getMessage(), 'Duplicate') === false &&
|
if (strpos($e2->getMessage(), 'Duplicate') === false &&
|
||||||
strpos($e->getMessage(), 'already exists') === false) {
|
strpos($e2->getMessage(), 'already exists') === false &&
|
||||||
throw $e;
|
strpos($e2->getMessage(), 'Table') === false) {
|
||||||
|
throw $e2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -497,6 +525,51 @@ class InstallerController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse SQL statements from a SQL file (fallback method)
|
||||||
|
*/
|
||||||
|
private function parseSqlStatements(string $sql): array
|
||||||
|
{
|
||||||
|
// Remove comments
|
||||||
|
$sql = preg_replace('/--.*$/m', '', $sql);
|
||||||
|
$sql = preg_replace('/\/\*.*?\*\//s', '', $sql);
|
||||||
|
|
||||||
|
// Split by semicolon, but be more careful about it
|
||||||
|
$statements = [];
|
||||||
|
$current = '';
|
||||||
|
$inString = false;
|
||||||
|
$stringChar = '';
|
||||||
|
|
||||||
|
for ($i = 0; $i < strlen($sql); $i++) {
|
||||||
|
$char = $sql[$i];
|
||||||
|
|
||||||
|
if (!$inString && ($char === '"' || $char === "'")) {
|
||||||
|
$inString = true;
|
||||||
|
$stringChar = $char;
|
||||||
|
} elseif ($inString && $char === $stringChar) {
|
||||||
|
// Check for escaped quotes
|
||||||
|
if ($i > 0 && $sql[$i-1] !== '\\') {
|
||||||
|
$inString = false;
|
||||||
|
}
|
||||||
|
} elseif (!$inString && $char === ';') {
|
||||||
|
$statements[] = trim($current);
|
||||||
|
$current = '';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$current .= $char;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the last statement if it doesn't end with semicolon
|
||||||
|
if (!empty(trim($current))) {
|
||||||
|
$statements[] = trim($current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_filter($statements, function($stmt) {
|
||||||
|
return !empty(trim($stmt));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate encryption key
|
* Generate encryption key
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user