index.php 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. <?php
  2. declare(strict_types=1);
  3. use App\Db\Connection;
  4. use App\Db\Migrator;
  5. use App\Http\Request;
  6. use App\Http\Response;
  7. use App\Http\Router;
  8. use App\Http\View;
  9. define('APP_ROOT', dirname(__DIR__));
  10. // ---------------------------------------------------------------------------
  11. // Autoload
  12. // ---------------------------------------------------------------------------
  13. $autoload = APP_ROOT . '/vendor/autoload.php';
  14. if (!is_file($autoload)) {
  15. http_response_code(500);
  16. header('Content-Type: text/plain; charset=utf-8');
  17. echo "Composer dependencies are not installed.\n";
  18. echo "Run: composer install (or rebuild the container).\n";
  19. exit;
  20. }
  21. require $autoload;
  22. // ---------------------------------------------------------------------------
  23. // Environment
  24. // ---------------------------------------------------------------------------
  25. if (is_file(APP_ROOT . '/.env')) {
  26. $dotenv = Dotenv\Dotenv::createImmutable(APP_ROOT);
  27. $dotenv->safeLoad();
  28. }
  29. $appEnv = getenv('APP_ENV') ?: 'production';
  30. if ($appEnv !== 'production') {
  31. ini_set('display_errors', '1');
  32. error_reporting(E_ALL);
  33. } else {
  34. ini_set('display_errors', '0');
  35. }
  36. // ---------------------------------------------------------------------------
  37. // Migrations — cheap no-op when already current
  38. // ---------------------------------------------------------------------------
  39. try {
  40. $pdo = Connection::pdo();
  41. (new Migrator($pdo))->migrate();
  42. } catch (\Throwable $e) {
  43. http_response_code(500);
  44. header('Content-Type: text/plain; charset=utf-8');
  45. echo "Database bootstrap failed.\n";
  46. if ($appEnv !== 'production') {
  47. echo $e->getMessage() . "\n";
  48. }
  49. exit;
  50. }
  51. // ---------------------------------------------------------------------------
  52. // Routing
  53. // ---------------------------------------------------------------------------
  54. $view = new View(APP_ROOT . '/views');
  55. $router = new Router();
  56. $router->get('/', function (Request $req) use ($view, $pdo): Response {
  57. $version = (int) $pdo->query('SELECT COALESCE(MAX(version), 0) FROM schema_version')->fetchColumn();
  58. return Response::html($view->render('home', [
  59. 'title' => 'Sprint Planner',
  60. 'schemaVersion' => $version,
  61. 'dbPath' => Connection::path(),
  62. 'appEnv' => $appEnv,
  63. ]));
  64. });
  65. $router->get('/healthz', function (): Response {
  66. return Response::text('ok');
  67. });
  68. // ---------------------------------------------------------------------------
  69. // Dispatch
  70. // ---------------------------------------------------------------------------
  71. $request = Request::fromGlobals();
  72. $response = $router->dispatch($request);
  73. $response->send();