1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2018 webtrees development team 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16declare(strict_types=1); 17 18namespace Fisharebest\Webtrees; 19 20use Closure; 21use Exception; 22use Fisharebest\Webtrees\Exceptions\Handler; 23use Fisharebest\Webtrees\Http\Middleware\CheckCsrf; 24use Fisharebest\Webtrees\Http\Middleware\CheckForMaintenanceMode; 25use Fisharebest\Webtrees\Http\Middleware\MiddlewareInterface; 26use Fisharebest\Webtrees\Http\Middleware\PageHitCounter; 27use Fisharebest\Webtrees\Http\Middleware\UseTransaction; 28use Symfony\Component\HttpFoundation\JsonResponse; 29use Symfony\Component\HttpFoundation\RedirectResponse; 30use Symfony\Component\HttpFoundation\Request; 31use Symfony\Component\HttpFoundation\Response; 32 33// Bootstrap the application 34require 'includes/session.php'; 35 36DebugBar::startMeasure('routing'); 37 38// The HTTP request. 39$request = Request::createFromGlobals(); 40$method = $request->getMethod(); 41$route = $request->get('route'); 42 43try { 44 // Most requests will need the current tree and user. 45 $all_trees = Tree::getAll(); 46 47 $tree = $all_trees[$request->get('ged')] ?? null; 48 49 // No tree specified/available? Choose one. 50 if ($tree === null && $method === 'GET') { 51 $tree = $all_trees[Site::getPreference('DEFAULT_GEDCOM')] ?? array_values($all_trees)[0] ?? null; 52 } 53 54 $request->attributes->set('tree', $tree); 55 $request->attributes->set('user', Auth::user()); 56 57 // Most layouts will require a tree for the page header/footer 58 View::share('tree', $tree); 59 60 // Load the routing table. 61 $routes = require 'routes/web.php'; 62 63 // Find the action for the selected route 64 $controller_action = $routes[$method . ':' . $route] ?? 'ErrorController@noRouteFound'; 65 66 // Create the controller 67 list($controller_name, $action) = explode('@', $controller_action); 68 $controller_class = __NAMESPACE__ . '\\Http\\Controllers\\' . $controller_name; 69 $controller = new $controller_class; 70 71 DebugBar::stopMeasure('routing'); 72 73 // Note that we can't stop this timer, as running the action will 74 // generate the response - which includes (and stops) the timer 75 DebugBar::startMeasure('controller_action', $controller_action); 76 77 $middleware_stack = [ 78 new CheckForMaintenanceMode, 79 ]; 80 81 if ($method === 'GET') { 82 $middleware_stack[] = new PageHitCounter; 83 } 84 85 if ($method === 'POST') { 86 $middleware_stack[] = new UseTransaction; 87 $middleware_stack[] = new CheckCsrf; 88 } 89 90 // Apply the middleware using the "onion" pattern. 91 $pipeline = array_reduce($middleware_stack, function (Closure $next, MiddlewareInterface $middleware): Closure { 92 // Create a closure to apply the middleware. 93 return function (Request $request) use ($middleware, $next): Response { 94 return $middleware->handle($request, $next); 95 }; 96 }, function (Request $request) use ($controller, $action): Response { 97 // Create a closure to generate the response. 98 return call_user_func([$controller, $action], $request); 99 }); 100 101 $response = call_user_func($pipeline, $request); 102} catch (Exception $exception) { 103 DebugBar::addThrowable($exception); 104 105 $response = (new Handler)->render($request, $exception); 106} 107 108// Send response 109if ($response instanceof RedirectResponse) { 110 // Show the debug data on the next page 111 DebugBar::stackData(); 112} elseif ($response instanceof JsonResponse) { 113 // Use HTTP headers and some jQuery to add debug to the current page. 114 DebugBar::sendDataInHeaders(); 115} 116 117$response->prepare($request)->send(); 118