. */ declare(strict_types=1); use Fisharebest\Webtrees\Database; use Fisharebest\Webtrees\DebugBar; use Fisharebest\Webtrees\Exceptions\Handler; use Fisharebest\Webtrees\Http\Controllers\SetupController; use Fisharebest\Webtrees\Http\Middleware\BootModules; use Fisharebest\Webtrees\Http\Middleware\CheckCsrf; use Fisharebest\Webtrees\Http\Middleware\CheckForMaintenanceMode; use Fisharebest\Webtrees\Http\Middleware\DebugBarData; use Fisharebest\Webtrees\Http\Middleware\Housekeeping; use Fisharebest\Webtrees\Http\Middleware\MiddlewareInterface; use Fisharebest\Webtrees\Http\Middleware\UseFilesystem; use Fisharebest\Webtrees\Http\Middleware\UseLocale; use Fisharebest\Webtrees\Http\Middleware\UseSession; use Fisharebest\Webtrees\Http\Middleware\UseTheme; use Fisharebest\Webtrees\Http\Middleware\UseTransaction; use Fisharebest\Webtrees\Http\Middleware\UseTree; use Fisharebest\Webtrees\Services\MigrationService; use Fisharebest\Webtrees\Services\ModuleService; use Fisharebest\Webtrees\Services\TimeoutService; use Fisharebest\Webtrees\Webtrees; use Illuminate\Cache\ArrayStore; use Illuminate\Cache\Repository; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; require __DIR__ . '/vendor/autoload.php'; const WT_ROOT = __DIR__ . DIRECTORY_SEPARATOR; Webtrees::init(); // Initialise the DebugBar for development. // Use `composer install --dev` on a development build to enable. // Note that you may need to increase the size of the fcgi buffers on nginx. // e.g. add these lines to your fastcgi_params file: // fastcgi_buffers 16 16m; // fastcgi_buffer_size 32m; DebugBar::init(class_exists('\\DebugBar\\StandardDebugBar')); // Use an array cache for database calls, etc. app()->instance('cache.array', new Repository(new ArrayStore())); // Start the timer. app()->instance(TimeoutService::class, new TimeoutService(microtime(true))); // Extract the request parameters. $request = Request::createFromGlobals(); app()->instance(Request::class, $request); // Calculate the base URL, so we can generate absolute URLs. $request_uri = $request->getSchemeAndHttpHost() . $request->getRequestUri(); // Remove any PHP script name and parameters. $base_uri = preg_replace('/[^\/]+\.php(\?.*)?$/', '', $request_uri); define('WT_BASE_URL', $base_uri); try { // No config file? Run the setup wizard if (!file_exists(Webtrees::CONFIG_FILE)) { define('WT_DATA_DIR', 'data/'); /** @var SetupController $controller */ $controller = app(SetupController::class); $response = $controller->setup($request); $response->prepare($request)->send(); return; } $database_config = parse_ini_file(Webtrees::CONFIG_FILE); if ($database_config === false) { throw new Exception('Invalid config file: ' . Webtrees::CONFIG_FILE); } // Read the connection settings and create the database Database::connect($database_config); // Update the database schema, if necessary. app(MigrationService::class)->updateSchema('\Fisharebest\Webtrees\Schema', 'WT_SCHEMA_VERSION', Webtrees::SCHEMA_VERSION); // Middleware allows code to intercept the request before it reaches the controller, and to // intercept the response afterwards. // // +----------------------------------+ // | Middleware1 | // | +------------------------------+ | // | | Middleware2 | | // | | +--------------------------+ | | // | | | | | | // Request ----|-|-|-> Controller::action() --|-|-|---> Response // | | | | | | // | | +--------------------------+ | | // | | | | // | +------------------------------+ | // | | // +----------------------------------+ $middleware_stack = [ CheckForMaintenanceMode::class, UseFilesystem::class, UseSession::class, UseTree::class, UseLocale::class, UseTheme::class, BootModules::class, ]; if (class_exists(DebugBar::class)) { $middleware_stack[] = DebugBarData::class; } if ($request->getMethod() === Request::METHOD_GET) { $middleware_stack[] = Housekeeping::class; } if ($request->getMethod() === Request::METHOD_POST) { $middleware_stack[] = UseTransaction::class; $middleware_stack[] = CheckCsrf::class; } // Allow modules to provide middleware. foreach (app(ModuleService::class)->findByInterface(MiddlewareInterface::class) as $middleware) { $middleware_stack[] = $middleware; } // We build the pipeline from controller outwards, so process the last middleware first. $middleware_stack = array_reverse($middleware_stack); // Construct the core middleware *after* loading the modules, to reduce dependencies. $middleware_stack = array_map(function ($middleware): MiddlewareInterface { return $middleware instanceof MiddlewareInterface ? $middleware : app($middleware); }, $middleware_stack); // Create a pipleline, which applies the middleware as a nested function call. // // Response = Middleware1(Middleware2(Controller::action(Request))) $pipeline = array_reduce($middleware_stack, function (Closure $next, MiddlewareInterface $middleware): Closure { // Create a closure to apply the middleware. return function (Request $request) use ($middleware, $next): Response { return $middleware->handle($request, $next); }; }, function (Request $request): Response { // Load the route and routing table. $route = $request->get('route'); $routes = require 'routes/web.php'; // Find the controller and action for the selected route $controller_action = $routes[$request->getMethod() . ':' . $route] ?? 'ErrorController@noRouteFound'; [$controller_name, $action] = explode('@', $controller_action); $controller_class = '\\Fisharebest\\Webtrees\\Http\\Controllers\\' . $controller_name; $controller = app($controller_class); return app()->dispatch($controller, $action); }); $response = $pipeline($request); } catch (Throwable $exception) { $response = (new Handler())->render($request, $exception); } // Send response $response->prepare($request)->send();