|
- <?php
-
- declare(strict_types=1);
-
- use Core\App;
- use Core\Auth\KeycloakAuth;
- use Core\Auth\PermissionService;
- use Core\Database;
- use Core\Http\Session;
- use Core\MigrationManager;
- use Core\Response;
- use Core\View;
-
- // ── Framework helpers ─────────────────────────────────────────────────────────
-
- function app(): App
- {
- static $app = null;
-
- if ($app === null) {
- $app = new App();
- }
-
- return $app;
- }
-
- function view(string $view, array $data = []): Response
- {
- return View::render($view, $data);
- }
-
- function redirect(string $url): Response
- {
- return Response::redirect($url);
- }
-
- // ── Environment helpers ───────────────────────────────────────────────────────
-
- function env(string $key, mixed $default = null): mixed
- {
- $value = $_ENV[$key] ?? getenv($key);
-
- return ($value === false) ? $default : $value;
- }
-
- function loadEnv(string $path): void
- {
- if (!file_exists($path)) {
- return;
- }
-
- foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
- $line = trim($line);
-
- if ($line === '' || str_starts_with($line, '#') || !str_contains($line, '=')) {
- continue;
- }
-
- [$key, $value] = explode('=', $line, 2);
- $key = trim($key);
- $value = trim($value, " \t\"'");
-
- if (!isset($_ENV[$key]) && getenv($key) === false) {
- $_ENV[$key] = $value;
- putenv("{$key}={$value}");
- }
- }
- }
-
- // ── Session helper ────────────────────────────────────────────────────────────
-
- function session(): Session
- {
- static $session = null;
-
- if ($session === null) {
- $session = new Session();
- }
-
- return $session;
- }
-
- // ── Auth helper ───────────────────────────────────────────────────────────────
-
- function auth(): KeycloakAuth
- {
- static $auth = null;
-
- if ($auth === null) {
- $auth = new KeycloakAuth(session(), new PermissionService());
- }
-
- return $auth;
- }
-
- // ── Database helpers ──────────────────────────────────────────────────────────
-
- function ensureSqlServerDatabase(array $config): void
- {
- if (!str_starts_with($config['dsn'] ?? '', 'sqlsrv:')) {
- return;
- }
-
- preg_match('/Server=([^;]+)/', $config['dsn'], $serverMatch);
- preg_match('/Database=([^;]+)/', $config['dsn'], $dbMatch);
-
- if (empty($serverMatch[1]) || empty($dbMatch[1])) {
- return;
- }
-
- $server = $serverMatch[1];
- $dbName = $dbMatch[1];
-
- try {
- $masterPdo = new PDO(
- "sqlsrv:Server={$server};Database=master;LoginTimeout=5;TrustServerCertificate=1",
- $config['username'] ?? null,
- $config['password'] ?? null,
- [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
- );
-
- $check = $masterPdo->prepare('SELECT 1 FROM sys.databases WHERE name = ?');
- $check->execute([$dbName]);
-
- if (!$check->fetch()) {
- $safeName = str_replace(']', ']]', $dbName);
- $masterPdo->exec("CREATE DATABASE [{$safeName}]");
- }
- } catch (\Throwable) {
- // Let the main connection fail with its own error if master access fails
- }
- }
-
- function database(): Database
- {
- static $database = null;
-
- if ($database === null) {
- /** @var array<string, mixed> $config */
- $config = require __DIR__ . '/../config/database.php';
-
- ensureSqlServerDatabase($config);
-
- $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;
- }
-
- // ── Session / CSRF helpers ────────────────────────────────────────────────────
-
- function ensureSessionStarted(): void
- {
- if (session_status() === PHP_SESSION_NONE) {
- session_start();
- }
- }
-
- 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 '<input type="hidden" name="_token" value="' . e(csrf_token()) . '">';
- }
-
- 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);
- }
|