2017-05-08 06:11:38 +00:00
< ? php
2024-08-24 15:27:00 +02:00
// Copyright (C) 2010-2024, the Friendica project
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
//
// SPDX-License-Identifier: AGPL-3.0-or-later
2020-02-09 16:18:46 +01:00
2017-05-08 06:11:38 +00:00
namespace Friendica ;
2024-12-18 22:16:34 +00:00
use Dice\Dice ;
2019-08-12 18:13:58 +02:00
use Friendica\App\Arguments ;
2019-08-15 17:23:00 +02:00
use Friendica\App\BaseURL ;
2024-11-06 07:21:50 +00:00
use Friendica\App\Mode ;
2024-11-10 12:02:31 +00:00
use Friendica\App\Page ;
2024-06-09 06:13:20 +00:00
use Friendica\App\Request ;
2024-11-10 12:02:31 +00:00
use Friendica\App\Router ;
2021-11-21 23:37:17 +01:00
use Friendica\Capabilities\ICanCreateResponses ;
2024-12-28 13:07:07 +00:00
use Friendica\Capabilities\ICanHandleRequests ;
2023-01-08 01:17:06 -05:00
use Friendica\Content\Nav ;
2025-01-09 08:17:43 +00:00
use Friendica\Core\Addon\Capability\ICanLoadAddons ;
2021-10-26 21:44:29 +02:00
use Friendica\Core\Config\Factory\Config ;
2025-01-05 22:02:38 +01:00
use Friendica\Core\Container ;
2024-12-26 08:27:02 +00:00
use Friendica\Core\Renderer ;
2022-10-20 21:27:32 +02:00
use Friendica\Core\Session\Capability\IHandleUserSessions ;
2022-12-16 21:59:32 +01:00
use Friendica\Database\Definition\DbaDefinition ;
use Friendica\Database\Definition\ViewDefinition ;
2021-03-10 09:40:42 -05:00
use Friendica\Module\Maintenance ;
2020-09-30 16:53:18 +02:00
use Friendica\Security\Authentication ;
2021-10-26 21:44:29 +02:00
use Friendica\Core\Config\Capability\IManageConfigValues ;
2024-12-26 10:07:03 +00:00
use Friendica\Core\L10n ;
2024-12-25 21:12:24 +00:00
use Friendica\Core\Logger\Capability\LogChannel ;
2021-10-26 21:44:29 +02:00
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues ;
2019-07-23 20:01:45 -04:00
use Friendica\Core\System ;
2024-12-26 10:07:03 +00:00
use Friendica\Core\Update ;
2019-08-12 18:13:58 +02:00
use Friendica\Module\Special\HTTPException as ModuleHTTPException ;
2019-05-01 21:33:33 -04:00
use Friendica\Network\HTTPException ;
2024-03-16 12:54:17 +00:00
use Friendica\Protocol\ATProtocol\DID ;
2024-12-25 21:12:24 +00:00
use Friendica\Security\ExAuth ;
2024-05-27 04:33:28 +00:00
use Friendica\Security\OpenWebAuth ;
2024-12-26 10:46:54 +00:00
use Friendica\Util\BasePath ;
2021-10-03 12:38:47 -04:00
use Friendica\Util\DateTimeFormat ;
2021-11-28 13:44:42 +01:00
use Friendica\Util\HTTPInputData ;
2019-03-19 06:44:51 +00:00
use Friendica\Util\HTTPSignature ;
2019-02-16 23:11:30 +01:00
use Friendica\Util\Profiler ;
2024-12-20 10:07:59 +00:00
use Psr\Http\Message\ServerRequestInterface ;
2018-12-30 21:42:56 +01:00
use Psr\Log\LoggerInterface ;
2017-05-11 11:53:04 -04:00
2017-05-08 06:11:38 +00:00
/**
2020-01-19 06:05:23 +00:00
* Our main application structure for the life of this page .
2017-05-08 06:11:38 +00:00
*
* Primarily deals with the URL that got us here
* and tries to make some sense of it , and
* stores our page contents and config storage
* and anything else that might need to be passed around
* before we spit the page out .
*
*/
2024-12-18 21:30:36 +00:00
class App
2018-01-15 19:13:21 -05:00
{
2022-10-17 10:37:48 +00:00
const PLATFORM = 'Friendica' ;
2024-12-31 22:13:29 +01:00
const CODENAME = 'Interrupted Fern' ;
2025-01-02 02:03:58 +01:00
const VERSION = '2025.02-dev' ;
2022-10-17 10:37:48 +00:00
2025-01-05 22:02:38 +01:00
public static function fromContainer ( Container $container ) : self
2024-12-18 22:16:34 +00:00
{
2025-01-05 22:02:38 +01:00
return new self ( $container );
2024-12-18 22:16:34 +00:00
}
2024-12-19 20:24:24 +00:00
/**
2025-01-05 22:02:38 +01:00
* @ var Container
2024-12-19 20:24:24 +00:00
*/
private $container ;
2018-10-06 16:27:20 +02:00
/**
2024-11-06 07:21:50 +00:00
* @ var Mode The Mode of the Application
2018-10-06 16:27:20 +02:00
*/
private $mode ;
2018-10-09 19:58:58 +02:00
/**
2019-04-08 21:12:10 +02:00
* @ var BaseURL
2018-10-09 19:58:58 +02:00
*/
2019-04-08 21:12:10 +02:00
private $baseURL ;
2018-10-09 19:58:58 +02:00
2024-06-09 06:13:20 +00:00
/** @var string */
private $requestId ;
2024-05-27 04:33:28 +00:00
/** @var Authentication */
private $auth ;
2018-12-30 21:42:56 +01:00
/**
2021-10-26 21:44:29 +02:00
* @ var IManageConfigValues The config
2019-02-03 22:22:04 +01:00
*/
private $config ;
2019-02-17 21:12:12 +01:00
/**
* @ var LoggerInterface The logger
2018-12-30 21:42:56 +01:00
*/
private $logger ;
2019-02-03 22:22:04 +01:00
/**
2019-02-16 23:11:30 +01:00
* @ var Profiler The profiler of this app
2019-02-03 22:22:04 +01:00
*/
2019-02-16 23:11:30 +01:00
private $profiler ;
2019-02-03 22:22:04 +01:00
2019-07-09 21:44:02 +02:00
/**
* @ var L10n The translator
*/
private $l10n ;
2019-08-12 18:13:58 +02:00
/**
* @ var App\Arguments
*/
private $args ;
2022-10-20 22:06:25 +02:00
/**
* @ var IHandleUserSessions
*/
2022-10-23 20:41:17 +02:00
private $session ;
2022-10-20 22:06:25 +02:00
2024-11-06 12:26:33 +00:00
/**
* @ var AppHelper $appHelper
*/
private $appHelper ;
2025-01-05 22:02:38 +01:00
private function __construct ( Container $container )
2024-12-20 12:30:05 +00:00
{
2024-12-19 20:24:24 +00:00
$this -> container = $container ;
2024-12-20 13:24:25 +00:00
}
public function processRequest ( ServerRequestInterface $request , float $start_time ) : void
{
2025-01-05 22:02:38 +01:00
$this -> container -> addRule ( Mode :: class , [
2024-12-25 21:27:08 +00:00
'call' => [
[ 'determineRunMode' , [ false , $request -> getServerParams ()], Dice :: CHAIN_CALL ],
],
]);
2025-01-09 08:17:43 +00:00
$this -> setupContainerForAddons ();
2025-01-05 22:02:38 +01:00
$this -> container -> setup ( LogChannel :: APP , false );
2024-12-23 15:30:42 +00:00
2024-12-20 12:30:05 +00:00
$this -> requestId = $this -> container -> create ( Request :: class ) -> getRequestId ();
$this -> auth = $this -> container -> create ( Authentication :: class );
$this -> config = $this -> container -> create ( IManageConfigValues :: class );
$this -> mode = $this -> container -> create ( Mode :: class );
$this -> baseURL = $this -> container -> create ( BaseURL :: class );
$this -> logger = $this -> container -> create ( LoggerInterface :: class );
$this -> profiler = $this -> container -> create ( Profiler :: class );
$this -> l10n = $this -> container -> create ( L10n :: class );
$this -> args = $this -> container -> create ( Arguments :: class );
$this -> session = $this -> container -> create ( IHandleUserSessions :: class );
$this -> appHelper = $this -> container -> create ( AppHelper :: class );
2024-11-17 19:53:17 +00:00
2024-12-26 08:45:57 +00:00
$this -> loadSetupForFrontend (
$request ,
2024-12-20 10:04:02 +00:00
$this -> container -> create ( DbaDefinition :: class ),
$this -> container -> create ( ViewDefinition :: class ),
);
2024-12-20 10:05:13 +00:00
2024-12-26 08:29:11 +00:00
$this -> registerTemplateEngine ();
2024-12-20 10:05:13 +00:00
$this -> mode -> setExecutor ( Mode :: INDEX );
2024-12-20 10:07:59 +00:00
$this -> runFrontend (
2024-12-20 13:38:38 +00:00
$this -> container -> create ( IManagePersonalConfigValues :: class ),
$this -> container -> create ( Page :: class ),
$this -> container -> create ( Nav :: class ),
$this -> container -> create ( ModuleHTTPException :: class ),
2024-12-20 10:07:59 +00:00
$start_time ,
2024-12-26 11:33:00 +00:00
$request
2024-12-20 10:07:59 +00:00
);
2024-12-20 10:04:02 +00:00
}
2025-01-08 22:20:06 +00:00
public function processConsole ( array $argv ) : void
{
2025-01-09 08:17:43 +00:00
$this -> setupContainerForAddons ();
2025-01-09 08:36:47 +00:00
$this -> registerTemplateEngine ();
2025-01-08 22:20:06 +00:00
( \Friendica\Core\Console :: create ( $this -> container , $argv )) -> execute ();
}
2024-12-25 21:12:24 +00:00
public function processEjabberd () : void
{
2025-01-09 08:17:43 +00:00
$this -> setupContainerForAddons ();
2025-01-05 22:02:38 +01:00
$this -> container -> setup ( LogChannel :: AUTH_JABBERED , false );
2024-12-25 21:12:24 +00:00
2025-01-09 08:36:47 +00:00
$this -> registerTemplateEngine ();
2024-12-26 10:46:54 +00:00
/** @var BasePath */
$basePath = $this -> container -> create ( BasePath :: class );
2024-12-25 21:12:24 +00:00
// Check the database structure and possibly fixes it
2024-12-26 10:46:54 +00:00
Update :: check ( $basePath -> getPath (), true );
2024-12-25 21:12:24 +00:00
$appMode = $this -> container -> create ( Mode :: class );
if ( $appMode -> isNormal ()) {
/** @var ExAuth $oAuth */
$oAuth = $this -> container -> create ( ExAuth :: class );
$oAuth -> readStdin ();
}
}
2025-01-09 08:17:43 +00:00
private function setupContainerForAddons () : void
{
/** @var ICanLoadAddons $addonLoader */
$addonLoader = $this -> container -> create ( ICanLoadAddons :: class );
foreach ( $addonLoader -> getActiveAddonConfig ( 'dependencies' ) as $name => $rule ) {
$this -> container -> addRule ( $name , $rule );
}
}
2024-12-26 08:27:02 +00:00
private function registerTemplateEngine () : void
{
Renderer :: registerTemplateEngine ( 'Friendica\Render\FriendicaSmartyEngine' );
}
2019-08-15 16:18:08 +02:00
/**
* Load the whole app instance
*/
2024-12-26 08:45:57 +00:00
private function loadSetupForFrontend ( ServerRequestInterface $request , DbaDefinition $dbaDefinition , ViewDefinition $viewDefinition )
2019-08-15 16:18:08 +02:00
{
2023-05-04 17:48:13 +02:00
if ( $this -> config -> get ( 'system' , 'ini_max_execution_time' ) !== false ) {
set_time_limit (( int ) $this -> config -> get ( 'system' , 'ini_max_execution_time' ));
}
if ( $this -> config -> get ( 'system' , 'ini_pcre_backtrack_limit' ) !== false ) {
ini_set ( 'pcre.backtrack_limit' , ( int ) $this -> config -> get ( 'system' , 'ini_pcre_backtrack_limit' ));
}
2018-07-02 07:23:47 -04:00
2022-10-18 04:35:06 +00:00
// Normally this constant is defined - but not if "pcntl" isn't installed
if ( ! defined ( 'SIGTERM' )) {
define ( 'SIGTERM' , 15 );
}
2021-10-03 12:38:47 -04:00
// Ensure that all "strtotime" operations do run timezone independent
date_default_timezone_set ( 'UTC' );
2019-08-15 16:18:08 +02:00
$this -> profiler -> reset ();
2018-06-25 20:38:41 -04:00
2024-11-06 07:21:50 +00:00
if ( $this -> mode -> has ( Mode :: DBAVAILABLE )) {
2019-02-23 01:24:08 +01:00
Core\Hook :: loadHooks ();
2024-12-26 08:45:57 +00:00
$loader = ( new Config ()) -> createConfigFileManager ( $this -> appHelper -> getBasePath (), $request -> getServerParams ());
2019-02-23 01:24:08 +01:00
Core\Hook :: callAll ( 'load_config' , $loader );
2022-12-16 21:59:32 +01:00
// Hooks are now working, reload the whole definitions with hook enabled
$dbaDefinition -> load ( true );
$viewDefinition -> load ( true );
2018-08-27 06:15:55 +02:00
}
$this -> loadDefaultTimezone ();
}
2018-06-27 23:05:38 -04:00
/**
* Loads the default timezone
*
* Include support for legacy $default_timezone
*
* @ global string $default_timezone
*/
2018-06-25 20:38:41 -04:00
private function loadDefaultTimezone ()
{
2019-02-03 22:22:04 +01:00
if ( $this -> config -> get ( 'system' , 'default_timezone' )) {
2021-10-03 12:38:47 -04:00
$timezone = $this -> config -> get ( 'system' , 'default_timezone' , 'UTC' );
2018-06-25 20:38:41 -04:00
} else {
global $default_timezone ;
2021-10-03 12:38:47 -04:00
$timezone = $default_timezone ? ? '' ? : 'UTC' ;
2018-06-25 20:38:41 -04:00
}
2024-11-06 12:26:33 +00:00
$this -> appHelper -> setTimeZone ( $timezone );
2018-06-25 20:38:41 -04:00
}
2018-10-21 22:24:47 -04:00
/**
* Frontend App script
*
* The App object behaves like a container and a dispatcher at the same time , including a representation of the
* request and a representation of the response .
*
* This probably should change to limit the size of this monster method .
2019-08-12 18:13:58 +02:00
*
2021-10-26 21:44:29 +02:00
* @ param IManagePersonalConfigValues $pconfig
2024-11-10 12:02:31 +00:00
* @ param Page $page The Friendica page printing container
2022-12-26 21:17:32 +01:00
* @ param ModuleHTTPException $httpException The possible HTTP Exception container
2021-11-28 14:01:13 +01:00
* @ param float $start_time The start time of the overall script execution
2020-01-19 22:23:44 +01:00
*
2019-10-06 11:18:51 -04:00
* @ throws HTTPException\InternalServerErrorException
* @ throws \ImagickException
2018-10-21 22:24:47 -04:00
*/
2024-12-20 13:24:25 +00:00
private function runFrontend (
2024-11-10 12:02:31 +00:00
IManagePersonalConfigValues $pconfig ,
Page $page ,
Nav $nav ,
ModuleHTTPException $httpException ,
float $start_time ,
2024-12-26 11:33:00 +00:00
ServerRequestInterface $request
2024-11-10 12:02:31 +00:00
) {
2024-12-26 11:41:27 +00:00
$httpInput = new HTTPInputData ( $request -> getServerParams ());
2024-12-26 11:33:45 +00:00
$serverVars = $request -> getServerParams ();
2024-12-26 11:35:32 +00:00
$queryVars = $request -> getQueryParams ();
2024-12-26 11:33:00 +00:00
2024-12-26 11:33:45 +00:00
$requeststring = ( $serverVars [ 'REQUEST_METHOD' ] ? ? '' ) . ' ' . ( $serverVars [ 'REQUEST_URI' ] ? ? '' ) . ' ' . ( $serverVars [ 'SERVER_PROTOCOL' ] ? ? '' );
$this -> logger -> debug ( 'Request received' , [ 'address' => $serverVars [ 'REMOTE_ADDR' ] ? ? '' , 'request' => $requeststring , 'referer' => $serverVars [ 'HTTP_REFERER' ] ? ? '' , 'user-agent' => $serverVars [ 'HTTP_USER_AGENT' ] ? ? '' ]);
2023-10-26 03:41:35 +00:00
$request_start = microtime ( true );
2025-01-02 02:03:58 +01:00
$request = $_REQUEST ;
2023-09-11 08:47:35 +00:00
2020-12-10 00:02:23 +00:00
$this -> profiler -> set ( $start_time , 'start' );
2020-12-09 22:10:27 +00:00
$this -> profiler -> set ( microtime ( true ), 'classinit' );
2021-11-19 22:47:49 +01:00
$moduleName = $this -> args -> getModuleName ();
2022-09-20 16:30:56 +02:00
$page -> setLogging ( $this -> args -> getMethod (), $this -> args -> getModuleName (), $this -> args -> getCommand ());
2019-08-12 18:13:58 +02:00
2019-07-23 20:01:45 -04:00
try {
// Missing DB connection: ERROR
2024-11-06 07:21:50 +00:00
if ( $this -> mode -> has ( Mode :: LOCALCONFIGPRESENT ) && ! $this -> mode -> has ( Mode :: DBAVAILABLE )) {
2022-01-03 22:29:26 +01:00
throw new HTTPException\InternalServerErrorException ( $this -> l10n -> t ( 'Apologies but the website is unavailable at the moment.' ));
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2019-08-15 16:18:08 +02:00
if ( ! $this -> mode -> isInstall ()) {
2019-07-23 20:01:45 -04:00
// Force SSL redirection
2023-02-18 20:47:52 +01:00
if ( $this -> config -> get ( 'system' , 'force_ssl' ) &&
2024-12-26 11:33:45 +00:00
( empty ( $serverVars [ 'HTTPS' ]) || $serverVars [ 'HTTPS' ] === 'off' ) &&
( empty ( $serverVars [ 'HTTP_X_FORWARDED_PROTO' ]) || $serverVars [ 'HTTP_X_FORWARDED_PROTO' ] === 'http' ) &&
! empty ( $serverVars [ 'REQUEST_METHOD' ]) &&
$serverVars [ 'REQUEST_METHOD' ] === 'GET' ) {
2023-02-18 20:47:52 +01:00
System :: externalRedirect ( $this -> baseURL . '/' . $this -> args -> getQueryString ());
2019-07-23 20:01:45 -04:00
}
Core\Hook :: callAll ( 'init_1' );
2019-03-19 06:44:51 +00:00
}
2024-12-26 11:33:45 +00:00
DID :: routeRequest ( $this -> args -> getCommand (), $serverVars );
2024-03-16 12:54:17 +00:00
2020-10-02 09:31:39 +00:00
if ( $this -> mode -> isNormal () && ! $this -> mode -> isBackend ()) {
2024-12-26 11:33:45 +00:00
$requester = HTTPSignature :: getSigner ( '' , $serverVars );
2019-07-23 20:01:45 -04:00
if ( ! empty ( $requester )) {
2024-05-27 04:33:28 +00:00
OpenWebAuth :: addVisitorCookieForHandle ( $requester );
2018-10-21 22:24:47 -04:00
}
}
2019-07-23 20:01:45 -04:00
// ZRL
2024-12-26 11:35:32 +00:00
if ( ! empty ( $queryVars [ 'zrl' ]) && $this -> mode -> isNormal () && ! $this -> mode -> isBackend () && ! $this -> session -> getLocalUserId ()) {
2022-12-07 22:24:01 -05:00
// Only continue when the given profile link seems valid.
2021-12-08 20:23:07 +00:00
// Valid profile links contain a path with "/profile/" and no query parameters
2024-12-26 11:35:32 +00:00
if (( parse_url ( $queryVars [ 'zrl' ], PHP_URL_QUERY ) == '' ) &&
strpos ( parse_url ( $queryVars [ 'zrl' ], PHP_URL_PATH ) ? ? '' , '/profile/' ) !== false ) {
$this -> auth -> setUnauthenticatedVisitor ( $queryVars [ 'zrl' ]);
2024-05-27 04:33:28 +00:00
OpenWebAuth :: zrlInit ();
2021-12-08 20:23:07 +00:00
} else {
// Someone came with an invalid parameter, maybe as a DDoS attempt
// We simply stop processing here
2024-12-26 11:35:32 +00:00
$this -> logger -> debug ( 'Invalid ZRL parameter.' , [ 'zrl' => $queryVars [ 'zrl' ]]);
2021-12-08 20:23:07 +00:00
throw new HTTPException\ForbiddenException ();
2019-07-23 20:01:45 -04:00
}
}
2018-10-21 22:24:47 -04:00
2024-12-26 11:35:32 +00:00
if ( ! empty ( $queryVars [ 'owt' ]) && $this -> mode -> isNormal ()) {
$token = $queryVars [ 'owt' ];
2024-05-27 04:33:28 +00:00
OpenWebAuth :: init ( $token );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2021-10-24 23:17:22 -04:00
if ( ! $this -> mode -> isBackend ()) {
2024-12-20 13:38:38 +00:00
$this -> auth -> withSession ();
2021-10-24 23:17:22 -04:00
}
2018-10-21 22:24:47 -04:00
2024-05-27 04:33:28 +00:00
if ( $this -> session -> isUnauthenticated ()) {
2019-07-23 20:01:45 -04:00
header ( 'X-Account-Management-Status: none' );
}
2018-10-21 22:24:47 -04:00
2019-07-23 20:01:45 -04:00
/*
* check_config () is responsible for running update scripts . These automatically
* update the DB schema whenever we push a new one out . It also checks to see if
* any addons have been added or removed and reacts accordingly .
*/
// in install mode, any url loads install module
// but we need "view" module for stylesheet
2019-08-15 16:18:08 +02:00
if ( $this -> mode -> isInstall () && $moduleName !== 'install' ) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'install' );
2019-07-23 20:01:45 -04:00
} else {
2024-11-08 16:20:55 +00:00
Core\Update :: check ( $this -> appHelper -> getBasePath (), false );
2019-07-23 20:01:45 -04:00
Core\Addon :: loadAddons ();
Core\Hook :: loadHooks ();
}
2018-10-21 22:24:47 -04:00
2024-05-20 19:36:40 +00:00
// Compatibility with Hubzilla
if ( $moduleName == 'rpost' ) {
$this -> baseURL -> redirect ( 'compose' );
}
2019-07-23 20:01:45 -04:00
// Compatibility with the Android Diaspora client
2019-08-12 18:13:58 +02:00
if ( $moduleName == 'stream' ) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'network?order=post' );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2019-08-12 18:13:58 +02:00
if ( $moduleName == 'conversations' ) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'message' );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2019-08-12 18:13:58 +02:00
if ( $moduleName == 'commented' ) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'network?order=comment' );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2019-08-12 18:13:58 +02:00
if ( $moduleName == 'liked' ) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'network?order=comment' );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2019-08-12 18:13:58 +02:00
if ( $moduleName == 'activity' ) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'network?conv=1' );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2019-08-12 18:13:58 +02:00
if (( $moduleName == 'status_messages' ) && ( $this -> args -> getCommand () == 'status_messages/new' )) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'bookmarklet' );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2019-08-12 18:13:58 +02:00
if (( $moduleName == 'user' ) && ( $this -> args -> getCommand () == 'user/edit' )) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'settings' );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2019-08-12 18:13:58 +02:00
if (( $moduleName == 'tag_followings' ) && ( $this -> args -> getCommand () == 'tag_followings/manage' )) {
2019-12-16 00:28:31 +01:00
$this -> baseURL -> redirect ( 'search' );
2019-07-23 20:01:45 -04:00
}
2018-10-21 22:24:47 -04:00
2021-07-25 05:08:29 +00:00
// Initialize module that can set the current theme in the init() method, either directly or via App->setProfileOwner
2019-12-30 20:02:09 +01:00
$page [ 'page_title' ] = $moduleName ;
2019-08-15 20:58:57 +02:00
2022-07-12 19:48:36 -04:00
// The "view" module is required to show the theme CSS
2024-11-06 07:21:50 +00:00
if ( ! $this -> mode -> isInstall () && ! $this -> mode -> has ( Mode :: MAINTENANCEDISABLED ) && $moduleName !== 'view' ) {
2024-12-28 13:07:07 +00:00
$module = $this -> createModuleInstance ( Maintenance :: class );
2021-03-10 09:40:42 -05:00
} else {
// determine the module class and save it to the module instance
// @todo there's an implicit dependency due SESSION::start(), so it has to be called here (yet)
2024-12-28 13:07:07 +00:00
$module = $this -> createModuleInstance ( null );
2021-03-10 09:40:42 -05:00
}
2018-10-21 22:24:47 -04:00
2023-07-08 21:01:48 -04:00
// Display can change depending on the requested language, so it shouldn't be cached whole
header ( 'Vary: Accept-Language' , false );
2021-11-28 13:44:42 +01:00
// Processes data from GET requests
2021-11-28 14:01:13 +01:00
$httpinput = $httpInput -> process ();
2024-11-19 08:40:48 +00:00
$input = array_merge ( $httpinput [ 'variables' ], $httpinput [ 'files' ], $request );
2021-11-28 13:44:42 +01:00
2022-12-26 21:17:32 +01:00
// Let the module run its internal process (init, get, post, ...)
2021-12-09 13:04:51 +00:00
$timestamp = microtime ( true );
2024-11-10 11:42:59 +00:00
$response = $module -> run ( $httpException , $input );
2021-12-09 13:04:51 +00:00
$this -> profiler -> set ( microtime ( true ) - $timestamp , 'content' );
2023-07-09 22:44:40 -04:00
// Wrapping HTML responses in the theme template
2021-11-22 00:07:09 +01:00
if ( $response -> getHeaderLine ( ICanCreateResponses :: X_HEADER ) === ICanCreateResponses :: TYPE_HTML ) {
2024-12-18 21:57:39 +00:00
$response = $page -> run ( $this -> appHelper , $this -> session , $this -> baseURL , $this -> args , $this -> mode , $response , $this -> l10n , $this -> profiler , $this -> config , $pconfig , $nav , $this -> session -> getLocalUserId ());
2021-11-21 21:52:36 +01:00
}
2023-07-09 22:44:40 -04:00
2024-12-26 11:33:45 +00:00
$this -> logger -> debug ( 'Request processed sucessfully' , [ 'response' => $response -> getStatusCode (), 'address' => $serverVars [ 'REMOTE_ADDR' ] ? ? '' , 'request' => $requeststring , 'referer' => $serverVars [ 'HTTP_REFERER' ] ? ? '' , 'user-agent' => $serverVars [ 'HTTP_USER_AGENT' ] ? ? '' , 'duration' => number_format ( microtime ( true ) - $request_start , 3 )]);
$this -> logSlowCalls ( microtime ( true ) - $request_start , $response -> getStatusCode (), $requeststring , $serverVars [ 'HTTP_USER_AGENT' ] ? ? '' );
2023-09-21 09:17:38 -04:00
System :: echoResponse ( $response );
2019-08-15 16:18:08 +02:00
} catch ( HTTPException $e ) {
2024-12-26 11:33:45 +00:00
$this -> logger -> debug ( 'Request processed with exception' , [ 'response' => $e -> getCode (), 'address' => $serverVars [ 'REMOTE_ADDR' ] ? ? '' , 'request' => $requeststring , 'referer' => $serverVars [ 'HTTP_REFERER' ] ? ? '' , 'user-agent' => $serverVars [ 'HTTP_USER_AGENT' ] ? ? '' , 'duration' => number_format ( microtime ( true ) - $request_start , 3 )]);
$this -> logSlowCalls ( microtime ( true ) - $request_start , $e -> getCode (), $requeststring , $serverVars [ 'HTTP_USER_AGENT' ] ? ? '' );
2022-12-26 21:17:32 +01:00
$httpException -> rawContent ( $e );
2019-05-01 21:33:33 -04:00
}
2022-06-10 18:49:03 +00:00
$page -> logRuntime ( $this -> config , 'runFrontend' );
2018-10-20 18:19:55 +02:00
}
2018-10-13 20:02:04 +02:00
2024-12-28 13:07:07 +00:00
private function createModuleInstance ( ? string $moduleClass = null ) : ICanHandleRequests
{
/** @var Router $router */
$router = $this -> container -> create ( Router :: class );
2024-12-28 16:36:07 +00:00
$moduleClass = $moduleClass ? ? $router -> getModuleClass ();
2025-01-02 02:03:58 +01:00
$parameters = $router -> getParameters ();
2024-12-28 16:36:07 +00:00
$dice_profiler_threshold = $this -> config -> get ( 'system' , 'dice_profiler_threshold' , 0 );
$stamp = microtime ( true );
/** @var ICanHandleRequests $module */
$module = $this -> container -> create ( $moduleClass , $parameters );
if ( $dice_profiler_threshold > 0 ) {
$dur = floatval ( microtime ( true ) - $stamp );
if ( $dur >= $dice_profiler_threshold ) {
$this -> logger -> notice ( 'Dice module creation lasts too long.' , [ 'duration' => round ( $dur , 3 ), 'module' => $moduleClass , 'parameters' => $parameters ]);
}
}
return $module ;
2024-12-28 13:07:07 +00:00
}
2024-06-09 06:13:20 +00:00
/**
* Log slow page executions
*
* @ param float $duration
* @ param integer $code
* @ param string $request
* @ param string $agent
* @ return void
*/
private function logSlowCalls ( float $duration , int $code , string $request , string $agent )
{
$logfile = $this -> config -> get ( 'system' , 'page_execution_logfile' );
$loglimit = $this -> config -> get ( 'system' , 'page_execution_log_limit' );
if ( empty ( $logfile ) || empty ( $loglimit ) || ( $duration < $loglimit )) {
return ;
}
@ file_put_contents (
$logfile ,
DateTimeFormat :: utcNow () . " \t " . round ( $duration , 3 ) . " \t " .
$this -> requestId . " \t " . $code . " \t " .
$request . " \t " . $agent . " \n " ,
FILE_APPEND
);
}
2017-05-08 06:11:38 +00:00
}