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 Fisharebest\Webtrees\Http\Controllers\BaseController; 21use Fisharebest\Webtrees\Http\Controllers\ErrorController; 22use Symfony\Component\HttpFoundation\JsonResponse; 23use Symfony\Component\HttpFoundation\RedirectResponse; 24use Symfony\Component\HttpFoundation\Request; 25use Symfony\Component\HttpFoundation\Response; 26use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; 27use Throwable; 28 29// Bootstrap the application 30require 'includes/session.php'; 31 32DebugBar::startMeasure('routing'); 33 34// The HTTP request. 35$request = Request::createFromGlobals(); 36$method = $request->getMethod(); 37$route = $request->get('route'); 38 39// Most requests will need the current tree and user. 40$all_tree_names = array_keys(Tree::getNameList()); 41$first_tree_name = current($all_tree_names) ?? ''; 42$previous_tree_name = Session::get('GEDCOM', $first_tree_name); 43$default_tree_name = $previous_tree_name ?: Site::getPreference('DEFAULT_GEDCOM'); 44$tree_name = $request->get('ged', $default_tree_name); 45$tree = Tree::findByName($tree_name); 46Session::put('GEDCOM', $tree_name); 47 48$request->attributes->set('tree', $tree); 49$request->attributes->set('user', AUth::user()); 50 51// Load the routing table. 52$routes = require 'routes/web.php'; 53 54// Find the action for the selected route 55$controller_action = $routes[$method . ':' . $route] ?? 'ErrorController@noRouteFound'; 56 57// POST requests need a valid CSRF token 58$csrf_token = $request->get('csrf', $request->headers->get('HTTP_X_CSRF_TOKEN')); 59if ($method === 'POST' && $csrf_token !== Filter::getCsrfToken()) { 60 $controller_action = 'ErrorController@csrf'; 61} 62 63DebugBar::stopMeasure('routing'); 64 65DebugBar::startMeasure('create controller'); 66 67// Create the controller 68list($controller_name, $action) = explode('@', $controller_action); 69$controller_class = __NAMESPACE__ . '\\Http\\Controllers\\' . $controller_name; 70$controller = new $controller_class; 71 72DebugBar::stopMeasure('create controller'); 73 74// Note that we can't stop this timer, as running the action will 75// generate the response - which includes (and stops) the timer 76DebugBar::startMeasure('controller_action', $controller_action); 77 78try { 79 // Wrap POST requests in a database transaction. 80 if ($method === 'POST') { 81 Database::beginTransaction(); 82 $response = call_user_func([$controller, $action], $request); 83 Database::commit(); 84 } else { 85 $response = call_user_func([$controller, $action], $request); 86 } 87} catch (HttpExceptionInterface $ex) { 88 if ($request->isXmlHttpRequest()) { 89 $response = new Response($ex->getMessage(), $ex->getStatusCode()); 90 } else { 91 $controller = new ErrorController; 92 $response = $controller->errorResponse($ex); 93 } 94} catch (Throwable $ex) { 95 if ($method === 'POST') { 96 Database::rollBack(); 97 } 98 DebugBar::addThrowable($ex); 99 $controller = new ErrorController; 100 $response = $controller->errorResponse($ex); 101} 102 103// Send response 104if ($response instanceof RedirectResponse) { 105 // Show the debug data on the next page 106 DebugBar::stackData(); 107} elseif ($response instanceof JsonResponse) { 108 // Use HTTP headers and some jQuery to add debug to the current page. 109 DebugBar::sendDataInHeaders(); 110} 111 112return $response->prepare($request)->send(); 113