xref: /webtrees/index.php (revision a6afca4cf33b4e58e45d8100e7533e97799b5214)
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