PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_TIMEOUT => 5 ]); // Enable WAL mode for concurrency and performance $pdo->exec('PRAGMA journal_mode = WAL;'); $pdo->exec('PRAGMA foreign_keys = ON;'); // Initialize tables if needed init_db_schema($pdo); return $pdo; } function init_db_schema(PDO $pdo): void { $pdo->exec(" CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'admin', created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS announcements ( id INTEGER PRIMARY KEY AUTOINCREMENT, is_active INTEGER NOT NULL DEFAULT 1, type TEXT NOT NULL DEFAULT 'holiday', headline TEXT NOT NULL, message TEXT NOT NULL, start_date TEXT NULL, end_date TEXT NULL, show_banner INTEGER NOT NULL DEFAULT 1, show_in_hours INTEGER NOT NULL DEFAULT 1, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS menu_categories ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, description TEXT NULL, sort_order INTEGER NOT NULL DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS menu_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, category_id INTEGER NOT NULL REFERENCES menu_categories(id) ON DELETE CASCADE, name TEXT NOT NULL, description TEXT NULL, price TEXT NOT NULL, badge TEXT NULL, is_available INTEGER NOT NULL DEFAULT 1, sort_order INTEGER NOT NULL DEFAULT 0, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS pub_hours ( day_of_week INTEGER PRIMARY KEY, is_open INTEGER NOT NULL DEFAULT 0, open_time TEXT NULL, close_time TEXT NULL, kitchen_close_time TEXT NULL, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); "); // Seed default admin user if table is empty (username: admin / password: password) $stmt = $pdo->query("SELECT COUNT(*) as count FROM users"); $userCount = $stmt->fetchColumn(); if ($userCount == 0) { $defaultPassHash = password_hash('password', PASSWORD_DEFAULT); $insert = $pdo->prepare("INSERT INTO users (username, password_hash, role) VALUES (?, ?, 'admin')"); $insert->execute(['admin', $defaultPassHash]); } // Seed default weekly hours if the table is empty: closed Sun–Wed, // 4–10pm Thu–Sat with the kitchen closing at 9 — matches the hours the // site originally shipped with as hardcoded copy. $stmt = $pdo->query("SELECT COUNT(*) as count FROM pub_hours"); $hoursCount = $stmt->fetchColumn(); if ($hoursCount == 0) { $insert = $pdo->prepare(" INSERT INTO pub_hours (day_of_week, is_open, open_time, close_time, kitchen_close_time) VALUES (?, ?, ?, ?, ?) "); // 0=Sunday ... 6=Saturday $defaults = [ 0 => null, // Sunday — closed 1 => null, // Monday — closed 2 => null, // Tuesday — closed 3 => null, // Wednesday — closed 4 => ['16:00', '22:00', '21:00'], // Thursday 5 => ['16:00', '22:00', '21:00'], // Friday 6 => ['16:00', '22:00', '21:00'], // Saturday ]; foreach ($defaults as $day => $times) { if ($times === null) { $insert->execute([$day, 0, null, null, null]); } else { $insert->execute([$day, 1, $times[0], $times[1], $times[2]]); } } } }