php buildtrees,index.php

本文档展示了Webtrees在线家谱应用的部分源代码,涉及配置、错误处理、数据库连接、路由、中间件、主题初始化以及异常处理等方面。代码中包含了PHP错误报告、数据库连接设置、会话管理、国际化设置以及错误页面的呈现等关键功能。
摘要由CSDN通过智能技术生成

/**

* webtrees: online genealogy

* Copyright (C) 2018 webtrees development team

* This program is free software: you can redistribute it and/or modify

* it under the terms of the GNU General Public License as published by

* the Free Software Foundation, either version 3 of the License, or

* (at your option) any later version.

* This program is distributed in the hope that it will be useful,

* but WITHOUT ANY WARRANTY; without even the implied warranty of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

* GNU General Public License for more details.

* You should have received a copy of the GNU General Public License

* along with this program. If not, see .

*/

declare(strict_types=1);

namespace Fisharebest\Webtrees;

use Closure;

use DateTime;

use ErrorException;

use Exception;

use Fisharebest\Localization\Locale;

use Fisharebest\Localization\Locale\LocaleInterface;

use Fisharebest\Webtrees\Exceptions\Handler;

use Fisharebest\Webtrees\Http\Controllers\SetupController;

use Fisharebest\Webtrees\Http\Middleware\CheckCsrf;

use Fisharebest\Webtrees\Http\Middleware\CheckForMaintenanceMode;

use Fisharebest\Webtrees\Http\Middleware\Housekeeping;

use Fisharebest\Webtrees\Http\Middleware\PageHitCounter;

use Fisharebest\Webtrees\Http\Middleware\UseTransaction;

use Fisharebest\Webtrees\Services\TimeoutService;

use League\Flysystem\Adapter\Local;

use League\Flysystem\Filesystem;

use PDOException;

use Symfony\Component\HttpFoundation\JsonResponse;

use Symfony\Component\HttpFoundation\RedirectResponse;

use Symfony\Component\HttpFoundation\Request;

use Symfony\Component\HttpFoundation\Response;

use Throwable;

// Identify ourself

define('WT_WEBTREES', 'webtrees');

define('WT_VERSION', '2.0.0-dev');

define('WT_WEBTREES_URL', 'https://www.webtrees.net/');

// Location of our modules and themes. These are used as URLs and folder paths.

define('WT_MODULES_DIR', 'modules_v3/');

define('WT_THEMES_DIR', 'themes/');

define('WT_ASSETS_URL', 'public/assets-2.0.0/'); // See also webpack.mix.js

define('WT_CKEDITOR_BASE_URL', 'public/ckeditor-4.5.2-custom/');

// Enable debugging output on development builds

define('WT_DEBUG', strpos(WT_VERSION, 'dev') !== false);

// Required version of database tables/columns/indexes/etc.

define('WT_SCHEMA_VERSION', 40);

// Regular expressions for validating user input, etc.

define('WT_MINIMUM_PASSWORD_LENGTH', 6);

define('WT_REGEX_XREF', '[A-Za-z0-9:_-]+');

define('WT_REGEX_TAG', '[_A-Z][_A-Z0-9]*');

define('WT_REGEX_INTEGER', '-?\d+');

define('WT_REGEX_BYTES', '[0-9]+[bBkKmMgG]?');

define('WT_REGEX_PASSWORD', '.{' . WT_MINIMUM_PASSWORD_LENGTH . ',}');

define('WT_UTF8_BOM', "\xEF\xBB\xBF"); // U+FEFF (Byte order mark)

// Alternatives to BMD events for lists, charts, etc.

define('WT_EVENTS_BIRT', 'BIRT|CHR|BAPM|_BRTM|ADOP');

define('WT_EVENTS_DEAT', 'DEAT|BURI|CREM');

define('WT_EVENTS_MARR', 'MARR|_NMR');

define('WT_EVENTS_DIV', 'DIV|ANUL|_SEPR');

define('WT_ROOT', __DIR__ . DIRECTORY_SEPARATOR);

// We want to know about all PHP errors during development, and fewer in production.

if (WT_DEBUG) {

error_reporting(E_ALL | E_STRICT | E_NOTICE | E_DEPRECATED);

} else {

error_reporting(E_ALL);

}

require WT_ROOT . 'vendor/autoload.php';

// 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(WT_DEBUG && class_exists('\\DebugBar\\StandardDebugBar'));

// PHP requires a time zone to be set. We'll set a better one later on.

date_default_timezone_set('UTC');

// Calculate the base URL, so we can generate absolute URLs.

$request = Request::createFromGlobals();

$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);

// Convert PHP warnings/notices into exceptions

set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {

// Ignore errors that are silenced with '@'

if (error_reporting() & $errno) {

throw new ErrorException($errstr, 0, $errno, $errfile, $errline);

}

return true;

});

DebugBar::startMeasure('init database');

// Load our configuration file, so we can connect to the database

define('WT_CONFIG_FILE', 'data/config.ini.php');

if (!file_exists(WT_ROOT . WT_CONFIG_FILE)) {

// No config file. Set one up.

define('WT_DATA_DIR', 'data/');

$request = Request::createFromGlobals();

$response = (new SetupController())->setup($request);

$response->prepare($request)->send();

return;

}

// Connect to the database

try {

// Read the connection settings and create the database

Database::createInstance(parse_ini_file(WT_ROOT . 'data/config.ini.php'));

// Update the database schema, if necessary.

Database::updateSchema('\Fisharebest\Webtrees\Schema', 'WT_SCHEMA_VERSION', WT_SCHEMA_VERSION);

} catch (PDOException $ex) {

DebugBar::addThrowable($ex);

define('WT_DATA_DIR', 'data/');

I18N::init();

if ($ex->getCode() === 1045) {

// Error during connection?

$content = view('errors/database-connection', ['error' => $ex->getMessage()]);

} else {

// Error in a migration script?

$content = view('errors/database-error', ['error' => $ex->getMessage()]);

}

$html = view('layouts/error', ['content' => $content]);

$response = new Response($html, Response::HTTP_SERVICE_UNAVAILABLE);

$response->prepare($request)->send();

return;

} catch (Throwable $ex) {

DebugBar::addThrowable($ex);

define('WT_DATA_DIR', 'data/');

I18N::init();

$content = view('errors/database-connection', ['error' => $ex->getMessage()]);

$html = view('layouts/error', ['content' => $content]);

$response = new Response($html, Response::HTTP_SERVICE_UNAVAILABLE);

$response->prepare($request)->send();

return;

}

DebugBar::stopMeasure('init database');

// The config.ini.php file must always be in a fixed location.

// Other user files can be stored elsewhere...

define('WT_DATA_DIR', realpath(Site::getPreference('INDEX_DIRECTORY', 'data/')) . DIRECTORY_SEPARATOR);

// Some broken servers block access to their own temp folder using open_basedir...

$data_dir = new Filesystem(new Local(WT_DATA_DIR));

$data_dir->createDir('tmp');

putenv('TMPDIR=' . WT_DATA_DIR . 'tmp');

// Request more resources - if we can/want to

$memory_limit = Site::getPreference('MEMORY_LIMIT');

if ($memory_limit !== '' && strpos(ini_get('disable_functions'), 'ini_set') === false) {

ini_set('memory_limit', $memory_limit);

}

$max_execution_time = Site::getPreference('MAX_EXECUTION_TIME');

if ($max_execution_time !== '' && strpos(ini_get('disable_functions'), 'set_time_limit') === false) {

set_time_limit((int) $max_execution_time);

}

// Sessions

Session::start();

DebugBar::startMeasure('init i18n');

// With no parameters, init() looks to the environment to choose a language

define('WT_LOCALE', I18N::init());

Session::put('locale', WT_LOCALE);

DebugBar::stopMeasure('init i18n');

// Note that the database/webservers may not be synchronised, so use DB time throughout.

define('WT_TIMESTAMP', (int) Database::prepare("SELECT UNIX_TIMESTAMP()")->fetchOne());

// Users get their own time-zone. Visitors get the site time-zone.

try {

if (Auth::check()) {

date_default_timezone_set(Auth::user()->getPreference('TIMEZONE'));

} else {

date_default_timezone_set(Site::getPreference('TIMEZONE'));

}

} catch (ErrorException $ex) {

// Server upgrades and migrations can leave us with invalid timezone settings.

date_default_timezone_set('UTC');

}

define('WT_TIMESTAMP_OFFSET', (new DateTime('now'))->getOffset());

define('WT_CLIENT_JD', 2440588 + (int) ((WT_TIMESTAMP + WT_TIMESTAMP_OFFSET) / 86400));

// Update the last-login time no more than once a minute

if (WT_TIMESTAMP - Session::get('activity_time') >= 60) {

if (Session::get('masquerade') === null) {

Auth::user()->setPreference('sessiontime', (string) WT_TIMESTAMP);

}

Session::put('activity_time', WT_TIMESTAMP);

}

DebugBar::startMeasure('routing');

// The HTTP request.

$request = Request::createFromGlobals();

$route = $request->get('route');

try {

// Most requests will need the current tree and user.

$all_trees = Tree::getAll();

$tree = $all_trees[$request->get('ged')] ?? null;

// No tree specified/available? Choose one.

if ($tree === null && $request->getMethod() === Request::METHOD_GET) {

$tree = $all_trees[Site::getPreference('DEFAULT_GEDCOM')] ?? array_values($all_trees)[0] ?? null;

}

// Most layouts will require a tree for the page header/footer

View::share('tree', $tree);

// Load the routing table.

$routes = require 'routes/web.php';

// Find the controller and action for the selected route

$controller_action = $routes[$request->getMethod() . ':' . $route] ?? 'ErrorController@noRouteFound';

list($controller_name, $action) = explode('@', $controller_action);

$controller_class = __NAMESPACE__ . '\\Http\\Controllers\\' . $controller_name;

// Set up dependency injection for the controllers.

$resolver = new Resolver();

$resolver->bind(Resolver::class, $resolver);

$resolver->bind(Tree::class, $tree);

$resolver->bind(User::class, Auth::user());

$resolver->bind(LocaleInterface::class, Locale::create(WT_LOCALE));

$resolver->bind(TimeoutService::class, new TimeoutService(microtime(true)));

$resolver->bind(Filesystem::class, new Filesystem(new Local(WT_DATA_DIR)));

$controller = $resolver->resolve($controller_class);

DebugBar::stopMeasure('routing');

DebugBar::startMeasure('init theme');

// Last theme used?

$theme_id = Session::get('theme_id');

// Default for tree

if (!array_key_exists($theme_id, Theme::themeNames()) && $tree) {

$theme_id = $tree->getPreference('THEME_DIR');

}

// Default for site

if (!array_key_exists($theme_id, Theme::themeNames())) {

$theme_id = Site::getPreference('THEME_DIR');

}

// Default

if (!array_key_exists($theme_id, Theme::themeNames())) {

$theme_id = 'webtrees';

}

foreach (Theme::installedThemes() as $theme) {

if ($theme->themeId() === $theme_id) {

Theme::theme($theme)->init($request, $tree);

// Remember this setting

if (Site::getPreference('ALLOW_USER_THEMES') === '1') {

Session::put('theme_id', $theme_id);

}

break;

}

}

DebugBar::stopMeasure('init theme');

// Note that we can't stop this timer, as running the action will

// generate the response - which includes (and stops) the timer

DebugBar::startMeasure('controller_action', $controller_action);

$middleware_stack = [

CheckForMaintenanceMode::class,

];

if ($request->getMethod() === Request::METHOD_GET) {

$middleware_stack[] = PageHitCounter::class;

$middleware_stack[] = Housekeeping::class;

}

if ($request->getMethod() === Request::METHOD_POST) {

$middleware_stack[] = UseTransaction::class;

$middleware_stack[] = CheckCsrf::class;

}

// Apply the middleware using the "onion" pattern.

$pipeline = array_reduce($middleware_stack, function (Closure $next, string $middleware) use ($resolver): Closure {

// Create a closure to apply the middleware.

return function (Request $request) use ($middleware, $next, $resolver): Response {

return $resolver->resolve($middleware)->handle($request, $next);

};

}, function (Request $request) use ($controller, $action, $resolver): Response {

$resolver->bind(Request::class, $request);

return $resolver->dispatch($controller, $action);

});

$response = call_user_func($pipeline, $request);

} catch (Exception $exception) {

DebugBar::addThrowable($exception);

$response = (new Handler())->render($request, $exception);

}

// Send response

if ($response instanceof RedirectResponse) {

// Show the debug data on the next page

DebugBar::stackData();

} elseif ($response instanceof JsonResponse) {

// Use HTTP headers and some jQuery to add debug to the current page.

DebugBar::sendDataInHeaders();

}

$response->prepare($request)->send();

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值