$config */ $config = require __DIR__ . '/../config/database.php'; prepareSqliteDatabase($config['dsn'] ?? ''); $database = new Database($config); } return $database; } function migration_manager(): MigrationManager { static $migrationManager = null; if ($migrationManager === null) { $migrationManager = new MigrationManager(database(), __DIR__ . '/../database/migrations'); } return $migrationManager; } function ensureSessionStarted(): void { if (session_status() === PHP_SESSION_NONE) { session_start(); } } function prepareSqliteDatabase(string $dsn): void { if (!str_starts_with($dsn, 'sqlite:')) { return; } $path = substr($dsn, 7); if ($path === false || $path === '') { return; } $directory = dirname($path); if (!is_dir($directory)) { mkdir($directory, 0777, true); } if (!is_writable($directory)) { @chmod($directory, 0777); } if (!file_exists($path)) { touch($path); } if (!is_writable($path)) { @chmod($path, 0666); } } function e(?string $value): string { return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); } function asset(string $path): string { return '/' . ltrim($path, '/'); } function csrf_token(): string { ensureSessionStarted(); if (!isset($_SESSION['_csrf_token']) || !is_string($_SESSION['_csrf_token'])) { $_SESSION['_csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['_csrf_token']; } function csrf_field(): string { return ''; } function verify_csrf_token(?string $token): bool { ensureSessionStarted(); if (!is_string($token) || $token === '') { return false; } $sessionToken = $_SESSION['_csrf_token'] ?? null; return is_string($sessionToken) && hash_equals($sessionToken, $token); }