]> git.mxchange.org Git - friendica.git/commitdiff
Refactor App\Module to App\ModuleController and rename properties
authorPhilipp <admin@philipp.info>
Tue, 16 Nov 2021 21:34:49 +0000 (22:34 +0100)
committerPhilipp <admin@philipp.info>
Tue, 16 Nov 2021 21:40:39 +0000 (22:40 +0100)
index.php
src/App.php
src/App/Mode.php
src/App/Module.php [deleted file]
src/App/ModuleController.php [new file with mode: 0644]
src/App/Page.php
src/DI.php
static/dependencies.config.php
tests/src/App/ModeTest.php
tests/src/App/ModuleTest.php

index cfb5937368e06d2bbb834bd051346881d7c73f21..0afd2c7d3eefa8b0c9daf73cfdeb51164aabfe28 100644 (file)
--- a/index.php
+++ b/index.php
@@ -41,7 +41,7 @@ $a = \Friendica\DI::app();
 \Friendica\DI::mode()->setExecutor(\Friendica\App\Mode::INDEX);
 
 $a->runFrontend(
-       $dice->create(\Friendica\App\Module::class),
+       $dice->create(\Friendica\App\ModuleController::class),
        $dice->create(\Friendica\App\Router::class),
        $dice->create(\Friendica\Core\PConfig\Capability\IManagePersonalConfigValues::class),
        $dice->create(\Friendica\Security\Authentication::class),
index 63d28fc80cfa4f8866f5aa232e735dc5f9f4790d..2dd8f9d1ab1e0581a74f38b7432cb1b4492a822e 100644 (file)
@@ -25,7 +25,7 @@ use Dice\Dice;
 use Exception;
 use Friendica\App\Arguments;
 use Friendica\App\BaseURL;
-use Friendica\App\Module;
+use Friendica\App\ModuleController;
 use Friendica\Core\Config\Factory\Config;
 use Friendica\Module\Maintenance;
 use Friendica\Security\Authentication;
@@ -567,16 +567,16 @@ class App
         *
         * This probably should change to limit the size of this monster method.
         *
-        * @param App\Module                  $module The determined module
+        * @param App\ModuleController        $module The determined module
         * @param App\Router                  $router
         * @param IManagePersonalConfigValues $pconfig
-        * @param Authentication              $auth The Authentication backend of the node
-        * @param App\Page                    $page The Friendica page printing container
+        * @param Authentication              $auth   The Authentication backend of the node
+        * @param App\Page                    $page   The Friendica page printing container
         *
         * @throws HTTPException\InternalServerErrorException
         * @throws \ImagickException
         */
-       public function runFrontend(App\Module $module, App\Router $router, IManagePersonalConfigValues $pconfig, Authentication $auth, App\Page $page, Dice $dice, float $start_time)
+       public function runFrontend(App\ModuleController $module, App\Router $router, IManagePersonalConfigValues $pconfig, Authentication $auth, App\Page $page, Dice $dice, float $start_time)
        {
                $this->profiler->set($start_time, 'start');
                $this->profiler->set(microtime(true), 'classinit');
@@ -703,7 +703,7 @@ class App
                        $page['page_title'] = $moduleName;
 
                        if (!$this->mode->isInstall() && !$this->mode->has(App\Mode::MAINTENANCEDISABLED)) {
-                               $module = new Module('maintenance', new Maintenance());
+                               $module = new ModuleController('maintenance', new Maintenance());
                        } 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)
index 1087b08a053a2ece02640f61434179b16580ae51..4a1213ae12933cdf48e29d1d96a7e82af245f8ee 100644 (file)
@@ -139,14 +139,14 @@ class Mode
        /**
         * Checks if the site is called via a backend process
         *
-        * @param bool         $isBackend    True, if the call is from a backend script (daemon, worker, ...)
-        * @param Module       $module       The pre-loaded module (just name, not class!)
-        * @param array        $server       The $_SERVER variable
-        * @param MobileDetect $mobileDetect The mobile detection library
+        * @param bool             $isBackend    True, if the call is from a backend script (daemon, worker, ...)
+        * @param ModuleController $module       The pre-loaded module (just name, not class!)
+        * @param array            $server       The $_SERVER variable
+        * @param MobileDetect     $mobileDetect The mobile detection library
         *
         * @return Mode returns the determined mode
         */
-       public function determineRunMode(bool $isBackend, Module $module, array $server, MobileDetect $mobileDetect)
+       public function determineRunMode(bool $isBackend, ModuleController $module, array $server, MobileDetect $mobileDetect)
        {
                foreach (self::BACKEND_CONTENT_TYPES as $type) {
                        if (strpos(strtolower($server['HTTP_ACCEPT'] ?? ''), $type) !== false) {
diff --git a/src/App/Module.php b/src/App/Module.php
deleted file mode 100644 (file)
index 94caf63..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2010-2021, the Friendica project
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\App;
-
-use Dice\Dice;
-use Friendica\App;
-use Friendica\Capabilities\ICanHandleRequests;
-use Friendica\Core;
-use Friendica\Core\Config\Capability\IManageConfigValues;
-use Friendica\LegacyModule;
-use Friendica\Module\Home;
-use Friendica\Module\HTTPException\MethodNotAllowed;
-use Friendica\Module\HTTPException\PageNotFound;
-use Friendica\Network\HTTPException\MethodNotAllowedException;
-use Friendica\Network\HTTPException\NoContentException;
-use Friendica\Network\HTTPException\NotFoundException;
-use Friendica\Util\Profiler;
-use Psr\Log\LoggerInterface;
-
-/**
- * Holds the common context of the current, loaded module
- */
-class Module
-{
-       const DEFAULT       = 'home';
-       const DEFAULT_CLASS = Home::class;
-       /**
-        * A list of modules, which are backend methods
-        *
-        * @var array
-        */
-       const BACKEND_MODULES = [
-               '_well_known',
-               'api',
-               'dfrn_notify',
-               'feed',
-               'fetch',
-               'followers',
-               'following',
-               'hcard',
-               'hostxrd',
-               'inbox',
-               'manifest',
-               'nodeinfo',
-               'noscrape',
-               'objects',
-               'outbox',
-               'poco',
-               'post',
-               'pubsub',
-               'pubsubhubbub',
-               'receive',
-               'rsd_xml',
-               'salmon',
-               'statistics_json',
-               'xrd',
-       ];
-
-       /**
-        * @var string The module name
-        */
-       private $module;
-
-       /**
-        * @var ICanHandleRequests The module class
-        */
-       private $module_class;
-
-       /**
-        * @var bool true, if the module is a backend module
-        */
-       private $isBackend;
-
-       /**
-        * @var bool true, if the loaded addon is private, so we have to print out not allowed
-        */
-       private $printNotAllowedAddon;
-
-       /**
-        * @return string
-        */
-       public function getName()
-       {
-               return $this->module;
-       }
-
-       /**
-        * @return ICanHandleRequests The base class name
-        */
-       public function getClass(): ICanHandleRequests
-       {
-               return $this->module_class;
-       }
-
-       /**
-        * @return bool True, if the current module is a backend module
-        * @see Module::BACKEND_MODULES for a list
-        */
-       public function isBackend()
-       {
-               return $this->isBackend;
-       }
-
-       public function __construct(string $module = self::DEFAULT, ICanHandleRequests $module_class = null, bool $isBackend = false, bool $printNotAllowedAddon = false)
-       {
-               $defaultClass = static::DEFAULT_CLASS;
-
-               $this->module               = $module;
-               $this->module_class         = $module_class ?? new $defaultClass();
-               $this->isBackend            = $isBackend;
-               $this->printNotAllowedAddon = $printNotAllowedAddon;
-       }
-
-       /**
-        * Determines the current module based on the App arguments and the server variable
-        *
-        * @param Arguments $args   The Friendica arguments
-        *
-        * @return Module The module with the determined module
-        */
-       public function determineModule(Arguments $args)
-       {
-               if ($args->getArgc() > 0) {
-                       $module = str_replace('.', '_', $args->get(0));
-                       $module = str_replace('-', '_', $module);
-               } else {
-                       $module = self::DEFAULT;
-               }
-
-               // Compatibility with the Firefox App
-               if (($module == "users") && ($args->getCommand() == "users/sign_in")) {
-                       $module = "login";
-               }
-
-               $isBackend = in_array($module, Module::BACKEND_MODULES);;
-
-               return new Module($module, null, $isBackend, $this->printNotAllowedAddon);
-       }
-
-       /**
-        * Determine the class of the current module
-        *
-        * @param Arguments           $args   The Friendica execution arguments
-        * @param Router              $router The Friendica routing instance
-        * @param IManageConfigValues $config The Friendica Configuration
-        * @param Dice                $dice   The Dependency Injection container
-        *
-        * @return Module The determined module of this call
-        *
-        * @throws \Exception
-        */
-       public function determineClass(Arguments $args, Router $router, IManageConfigValues $config, Dice $dice)
-       {
-               $printNotAllowedAddon = false;
-
-               $module_class = null;
-               $module_parameters = [];
-               /**
-                * ROUTING
-                *
-                * From the request URL, routing consists of obtaining the name of a BaseModule-extending class of which the
-                * post() and/or content() static methods can be respectively called to produce a data change or an output.
-                **/
-               try {
-                       $module_class = $router->getModuleClass($args->getCommand());
-                       $module_parameters[] = $router->getModuleParameters();
-               } catch (MethodNotAllowedException $e) {
-                       $module_class = MethodNotAllowed::class;
-               } catch (NotFoundException $e) {
-                       // Then we try addon-provided modules that we wrap in the LegacyModule class
-                       if (Core\Addon::isEnabled($this->module) && file_exists("addon/{$this->module}/{$this->module}.php")) {
-                               //Check if module is an app and if public access to apps is allowed or not
-                               $privateapps = $config->get('config', 'private_addons', false);
-                               if ((!local_user()) && Core\Hook::isAddonApp($this->module) && $privateapps) {
-                                       $printNotAllowedAddon = true;
-                               } else {
-                                       include_once "addon/{$this->module}/{$this->module}.php";
-                                       if (function_exists($this->module . '_module')) {
-                                               $module_parameters[] = "addon/{$this->module}/{$this->module}.php";
-                                               $module_class        = LegacyModule::class;
-                                       }
-                               }
-                       }
-
-                       /* Finally, we look for a 'standard' program module in the 'mod' directory
-                        * We emulate a Module class through the LegacyModule class
-                        */
-                       if (!$module_class && file_exists("mod/{$this->module}.php")) {
-                               $module_parameters[] = "mod/{$this->module}.php";
-                               $module_class        = LegacyModule::class;
-                       }
-
-                       $module_class = $module_class ?: PageNotFound::class;
-               }
-
-               /** @var ICanHandleRequests $module */
-               $module = $dice->create($module_class, $module_parameters);
-
-               return new Module($this->module, $module, $this->isBackend, $printNotAllowedAddon);
-       }
-
-       /**
-        * Run the determined module class and calls all hooks applied to
-        *
-        * @param \Friendica\Core\L10n $l10n    The L10n instance
-        * @param App\BaseURL          $baseUrl The Friendica Base URL
-        * @param LoggerInterface      $logger  The Friendica logger
-        * @param array                $server  The $_SERVER variable
-        * @param array                $post    The $_POST variables
-        *
-        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
-        */
-       public function run(Core\L10n $l10n, App\BaseURL $baseUrl, LoggerInterface $logger, Profiler $profiler, array $server, array $post)
-       {
-               if ($this->printNotAllowedAddon) {
-                       notice($l10n->t("You must be logged in to use addons. "));
-               }
-
-               /* The URL provided does not resolve to a valid module.
-                *
-                * On Dreamhost sites, quite often things go wrong for no apparent reason and they send us to '/internal_error.html'.
-                * We don't like doing this, but as it occasionally accounts for 10-20% or more of all site traffic -
-                * we are going to trap this and redirect back to the requested page. As long as you don't have a critical error on your page
-                * this will often succeed and eventually do the right thing.
-                *
-                * Otherwise we are going to emit a 404 not found.
-                */
-               if ($this->module_class === PageNotFound::class) {
-                       $queryString = $server['QUERY_STRING'];
-                       // Stupid browser tried to pre-fetch our Javascript img template. Don't log the event or return anything - just quietly exit.
-                       if (!empty($queryString) && preg_match('/{[0-9]}/', $queryString) !== 0) {
-                               exit();
-                       }
-
-                       if (!empty($queryString) && ($queryString === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
-                               $logger->info('index.php: dreamhost_error_hack invoked.', ['Original URI' => $server['REQUEST_URI']]);
-                               $baseUrl->redirect($server['REQUEST_URI']);
-                       }
-
-                       $logger->debug('index.php: page not found.', ['request_uri' => $server['REQUEST_URI'], 'address' => $server['REMOTE_ADDR'], 'query' => $server['QUERY_STRING']]);
-               }
-
-               // @see https://github.com/tootsuite/mastodon/blob/c3aef491d66aec743a3a53e934a494f653745b61/config/initializers/cors.rb
-               if (substr($_REQUEST['pagename'] ?? '', 0, 12) == '.well-known/') {
-                       header('Access-Control-Allow-Origin: *');
-                       header('Access-Control-Allow-Headers: *');
-                       header('Access-Control-Allow-Methods: ' . Router::GET);
-                       header('Access-Control-Allow-Credentials: false');
-               } elseif (substr($_REQUEST['pagename'] ?? '', 0, 8) == 'profile/') {
-                       header('Access-Control-Allow-Origin: *');
-                       header('Access-Control-Allow-Headers: *');
-                       header('Access-Control-Allow-Methods: ' . Router::GET);
-                       header('Access-Control-Allow-Credentials: false');
-               } elseif (substr($_REQUEST['pagename'] ?? '', 0, 4) == 'api/') {
-                       header('Access-Control-Allow-Origin: *');
-                       header('Access-Control-Allow-Headers: *');
-                       header('Access-Control-Allow-Methods: ' . implode(',', Router::ALLOWED_METHODS));
-                       header('Access-Control-Allow-Credentials: false');
-                       header('Access-Control-Expose-Headers: Link');
-               } elseif (substr($_REQUEST['pagename'] ?? '', 0, 11) == 'oauth/token') {
-                       header('Access-Control-Allow-Origin: *');
-                       header('Access-Control-Allow-Headers: *');
-                       header('Access-Control-Allow-Methods: ' . Router::POST);
-                       header('Access-Control-Allow-Credentials: false');
-               }
-
-               // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
-               // @todo Check allowed methods per requested path
-               if ($server['REQUEST_METHOD'] === Router::OPTIONS) {
-                       header('Allow: ' . implode(',', Router::ALLOWED_METHODS));
-                       throw new NoContentException();
-               }
-
-               $placeholder = '';
-
-               $profiler->set(microtime(true), 'ready');
-               $timestamp = microtime(true);
-
-               Core\Hook::callAll($this->module . '_mod_init', $placeholder);
-
-               $this->module_class->init();
-
-               $profiler->set(microtime(true) - $timestamp, 'init');
-
-               if ($server['REQUEST_METHOD'] === Router::DELETE) {
-                       $this->module_class->delete();
-               }
-
-               if ($server['REQUEST_METHOD'] === Router::PATCH) {
-                       $this->module_class->patch();
-               }
-
-               if ($server['REQUEST_METHOD'] === Router::POST) {
-                       Core\Hook::callAll($this->module . '_mod_post', $post);
-                       $this->module_class->post();
-               }
-
-               if ($server['REQUEST_METHOD'] === Router::PUT) {
-                       $this->module_class->put();
-               }
-
-               // "rawContent" is especially meant for technical endpoints.
-               // This endpoint doesn't need any theme initialization or other comparable stuff.
-               $this->module_class->rawContent();
-       }
-}
diff --git a/src/App/ModuleController.php b/src/App/ModuleController.php
new file mode 100644 (file)
index 0000000..013859d
--- /dev/null
@@ -0,0 +1,326 @@
+<?php
+/**
+ * @copyright Copyright (C) 2010-2021, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\App;
+
+use Dice\Dice;
+use Friendica\App;
+use Friendica\Capabilities\ICanHandleRequests;
+use Friendica\Core;
+use Friendica\Core\Config\Capability\IManageConfigValues;
+use Friendica\LegacyModule;
+use Friendica\Module\Home;
+use Friendica\Module\HTTPException\MethodNotAllowed;
+use Friendica\Module\HTTPException\PageNotFound;
+use Friendica\Network\HTTPException\MethodNotAllowedException;
+use Friendica\Network\HTTPException\NoContentException;
+use Friendica\Network\HTTPException\NotFoundException;
+use Friendica\Util\Profiler;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Holds the common context of the current, loaded module
+ */
+class ModuleController
+{
+       const DEFAULT       = 'home';
+       const DEFAULT_CLASS = Home::class;
+       /**
+        * A list of modules, which are backend methods
+        *
+        * @var array
+        */
+       const BACKEND_MODULES = [
+               '_well_known',
+               'api',
+               'dfrn_notify',
+               'feed',
+               'fetch',
+               'followers',
+               'following',
+               'hcard',
+               'hostxrd',
+               'inbox',
+               'manifest',
+               'nodeinfo',
+               'noscrape',
+               'objects',
+               'outbox',
+               'poco',
+               'post',
+               'pubsub',
+               'pubsubhubbub',
+               'receive',
+               'rsd_xml',
+               'salmon',
+               'statistics_json',
+               'xrd',
+       ];
+
+       /**
+        * @var string The module name
+        */
+       private $moduleName;
+
+       /**
+        * @var ICanHandleRequests The module class
+        */
+       private $module;
+
+       /**
+        * @var bool true, if the module is a backend module
+        */
+       private $isBackend;
+
+       /**
+        * @var bool true, if the loaded addon is private, so we have to print out not allowed
+        */
+       private $printNotAllowedAddon;
+
+       /**
+        * @return string
+        */
+       public function getName()
+       {
+               return $this->moduleName;
+       }
+
+       /**
+        * @return ICanHandleRequests The base module object
+        */
+       public function getModule(): ICanHandleRequests
+       {
+               return $this->module;
+       }
+
+       /**
+        * @return bool True, if the current module is a backend module
+        * @see ModuleController::BACKEND_MODULES for a list
+        */
+       public function isBackend()
+       {
+               return $this->isBackend;
+       }
+
+       public function __construct(string $moduleName = self::DEFAULT, ICanHandleRequests $module = null, bool $isBackend = false, bool $printNotAllowedAddon = false)
+       {
+               $defaultClass = static::DEFAULT_CLASS;
+
+               $this->moduleName           = $moduleName;
+               $this->module               = $module ?? new $defaultClass();
+               $this->isBackend            = $isBackend;
+               $this->printNotAllowedAddon = $printNotAllowedAddon;
+       }
+
+       /**
+        * Determines the current module based on the App arguments and the server variable
+        *
+        * @param Arguments $args   The Friendica arguments
+        *
+        * @return ModuleController The module with the determined module
+        */
+       public function determineName(Arguments $args)
+       {
+               if ($args->getArgc() > 0) {
+                       $module = str_replace('.', '_', $args->get(0));
+                       $module = str_replace('-', '_', $module);
+               } else {
+                       $module = self::DEFAULT;
+               }
+
+               // Compatibility with the Firefox App
+               if (($module == "users") && ($args->getCommand() == "users/sign_in")) {
+                       $module = "login";
+               }
+
+               $isBackend = in_array($module, ModuleController::BACKEND_MODULES);
+               ;
+
+               return new ModuleController($module, null, $isBackend, $this->printNotAllowedAddon);
+       }
+
+       /**
+        * Determine the class of the current module
+        *
+        * @param Arguments           $args   The Friendica execution arguments
+        * @param Router              $router The Friendica routing instance
+        * @param IManageConfigValues $config The Friendica Configuration
+        * @param Dice                $dice   The Dependency Injection container
+        *
+        * @return ModuleController The determined module of this call
+        *
+        * @throws \Exception
+        */
+       public function determineClass(Arguments $args, Router $router, IManageConfigValues $config, Dice $dice)
+       {
+               $printNotAllowedAddon = false;
+
+               $module_class      = null;
+               $module_parameters = [];
+               /**
+                * ROUTING
+                *
+                * From the request URL, routing consists of obtaining the name of a BaseModule-extending class of which the
+                * post() and/or content() static methods can be respectively called to produce a data change or an output.
+                **/
+               try {
+                       $module_class        = $router->getModuleClass($args->getCommand());
+                       $module_parameters[] = $router->getModuleParameters();
+               } catch (MethodNotAllowedException $e) {
+                       $module_class = MethodNotAllowed::class;
+               } catch (NotFoundException $e) {
+                       // Then we try addon-provided modules that we wrap in the LegacyModule class
+                       if (Core\Addon::isEnabled($this->moduleName) && file_exists("addon/{$this->moduleName}/{$this->moduleName}.php")) {
+                               //Check if module is an app and if public access to apps is allowed or not
+                               $privateapps = $config->get('config', 'private_addons', false);
+                               if ((!local_user()) && Core\Hook::isAddonApp($this->moduleName) && $privateapps) {
+                                       $printNotAllowedAddon = true;
+                               } else {
+                                       include_once "addon/{$this->moduleName}/{$this->moduleName}.php";
+                                       if (function_exists($this->moduleName . '_module')) {
+                                               $module_parameters[] = "addon/{$this->moduleName}/{$this->moduleName}.php";
+                                               $module_class        = LegacyModule::class;
+                                       }
+                               }
+                       }
+
+                       /* Finally, we look for a 'standard' program module in the 'mod' directory
+                        * We emulate a Module class through the LegacyModule class
+                        */
+                       if (!$module_class && file_exists("mod/{$this->moduleName}.php")) {
+                               $module_parameters[] = "mod/{$this->moduleName}.php";
+                               $module_class        = LegacyModule::class;
+                       }
+
+                       $module_class = $module_class ?: PageNotFound::class;
+               }
+
+               /** @var ICanHandleRequests $module */
+               $module = $dice->create($module_class, $module_parameters);
+
+               return new ModuleController($this->moduleName, $module, $this->isBackend, $printNotAllowedAddon);
+       }
+
+       /**
+        * Run the determined module class and calls all hooks applied to
+        *
+        * @param \Friendica\Core\L10n $l10n    The L10n instance
+        * @param App\BaseURL          $baseUrl The Friendica Base URL
+        * @param LoggerInterface      $logger  The Friendica logger
+        * @param array                $server  The $_SERVER variable
+        * @param array                $post    The $_POST variables
+        *
+        * @throws \Friendica\Network\HTTPException\InternalServerErrorException
+        */
+       public function run(Core\L10n $l10n, App\BaseURL $baseUrl, LoggerInterface $logger, Profiler $profiler, array $server, array $post)
+       {
+               if ($this->printNotAllowedAddon) {
+                       notice($l10n->t("You must be logged in to use addons. "));
+               }
+
+               /* The URL provided does not resolve to a valid module.
+                *
+                * On Dreamhost sites, quite often things go wrong for no apparent reason and they send us to '/internal_error.html'.
+                * We don't like doing this, but as it occasionally accounts for 10-20% or more of all site traffic -
+                * we are going to trap this and redirect back to the requested page. As long as you don't have a critical error on your page
+                * this will often succeed and eventually do the right thing.
+                *
+                * Otherwise we are going to emit a 404 not found.
+                */
+               if ($this->module === PageNotFound::class) {
+                       $queryString = $server['QUERY_STRING'];
+                       // Stupid browser tried to pre-fetch our Javascript img template. Don't log the event or return anything - just quietly exit.
+                       if (!empty($queryString) && preg_match('/{[0-9]}/', $queryString) !== 0) {
+                               exit();
+                       }
+
+                       if (!empty($queryString) && ($queryString === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
+                               $logger->info('index.php: dreamhost_error_hack invoked.', ['Original URI' => $server['REQUEST_URI']]);
+                               $baseUrl->redirect($server['REQUEST_URI']);
+                       }
+
+                       $logger->debug('index.php: page not found.', ['request_uri' => $server['REQUEST_URI'], 'address' => $server['REMOTE_ADDR'], 'query' => $server['QUERY_STRING']]);
+               }
+
+               // @see https://github.com/tootsuite/mastodon/blob/c3aef491d66aec743a3a53e934a494f653745b61/config/initializers/cors.rb
+               if (substr($_REQUEST['pagename'] ?? '', 0, 12) == '.well-known/') {
+                       header('Access-Control-Allow-Origin: *');
+                       header('Access-Control-Allow-Headers: *');
+                       header('Access-Control-Allow-Methods: ' . Router::GET);
+                       header('Access-Control-Allow-Credentials: false');
+               } elseif (substr($_REQUEST['pagename'] ?? '', 0, 8) == 'profile/') {
+                       header('Access-Control-Allow-Origin: *');
+                       header('Access-Control-Allow-Headers: *');
+                       header('Access-Control-Allow-Methods: ' . Router::GET);
+                       header('Access-Control-Allow-Credentials: false');
+               } elseif (substr($_REQUEST['pagename'] ?? '', 0, 4) == 'api/') {
+                       header('Access-Control-Allow-Origin: *');
+                       header('Access-Control-Allow-Headers: *');
+                       header('Access-Control-Allow-Methods: ' . implode(',', Router::ALLOWED_METHODS));
+                       header('Access-Control-Allow-Credentials: false');
+                       header('Access-Control-Expose-Headers: Link');
+               } elseif (substr($_REQUEST['pagename'] ?? '', 0, 11) == 'oauth/token') {
+                       header('Access-Control-Allow-Origin: *');
+                       header('Access-Control-Allow-Headers: *');
+                       header('Access-Control-Allow-Methods: ' . Router::POST);
+                       header('Access-Control-Allow-Credentials: false');
+               }
+
+               // @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
+               // @todo Check allowed methods per requested path
+               if ($server['REQUEST_METHOD'] === Router::OPTIONS) {
+                       header('Allow: ' . implode(',', Router::ALLOWED_METHODS));
+                       throw new NoContentException();
+               }
+
+               $placeholder = '';
+
+               $profiler->set(microtime(true), 'ready');
+               $timestamp = microtime(true);
+
+               Core\Hook::callAll($this->moduleName . '_mod_init', $placeholder);
+
+               $this->module->init();
+
+               $profiler->set(microtime(true) - $timestamp, 'init');
+
+               if ($server['REQUEST_METHOD'] === Router::DELETE) {
+                       $this->module->delete();
+               }
+
+               if ($server['REQUEST_METHOD'] === Router::PATCH) {
+                       $this->module->patch();
+               }
+
+               if ($server['REQUEST_METHOD'] === Router::POST) {
+                       Core\Hook::callAll($this->moduleName . '_mod_post', $post);
+                       $this->module->post();
+               }
+
+               if ($server['REQUEST_METHOD'] === Router::PUT) {
+                       $this->module->put();
+               }
+
+               // "rawContent" is especially meant for technical endpoints.
+               // This endpoint doesn't need any theme initialization or other comparable stuff.
+               $this->module->rawContent();
+       }
+}
index 71d59f59d0b500eecafdde5edb2507e8849fa22e..f410f6aa2811ea7d39b3c3d97f020537f7882e6f 100644 (file)
@@ -191,14 +191,14 @@ class Page implements ArrayAccess
         * - head.tpl template
         *
         * @param App                         $app     The Friendica App instance
-        * @param Module                      $module  The loaded Friendica module
+        * @param ModuleController            $module  The loaded Friendica module
         * @param L10n                        $l10n    The l10n language instance
         * @param IManageConfigValues         $config  The Friendica configuration
         * @param IManagePersonalConfigValues $pConfig The Friendica personal configuration (for user)
         *
         * @throws HTTPException\InternalServerErrorException
         */
-       private function initHead(App $app, Module $module, L10n $l10n, IManageConfigValues $config, IManagePersonalConfigValues $pConfig)
+       private function initHead(App $app, ModuleController $module, L10n $l10n, IManageConfigValues $config, IManagePersonalConfigValues $pConfig)
        {
                $interval = ((local_user()) ? $pConfig->get(local_user(), 'system', 'update_interval') : 40000);
 
@@ -337,17 +337,17 @@ class Page implements ArrayAccess
         * - module content
         * - hooks for content
         *
-        * @param Module $module The module
-        * @param Mode   $mode   The Friendica execution mode
+        * @param ModuleController $module The module
+        * @param Mode             $mode   The Friendica execution mode
         *
         * @throws HTTPException\InternalServerErrorException
         */
-       private function initContent(Module $module, Mode $mode)
+       private function initContent(ModuleController $module, Mode $mode)
        {
                $content = '';
 
                try {
-                       $moduleClass = $module->getClass();
+                       $moduleClass = $module->getModule();
 
                        $arr = ['content' => $content];
                        Hook::callAll($moduleClass->getClassName() . '_mod_content', $arr);
@@ -389,14 +389,14 @@ class Page implements ArrayAccess
         * @param App                         $app     The Friendica App
         * @param BaseURL                     $baseURL The Friendica Base URL
         * @param Mode                        $mode    The current node mode
-        * @param Module                      $module  The loaded Friendica module
+        * @param ModuleController            $module  The loaded Friendica module
         * @param L10n                        $l10n    The l10n language class
         * @param IManageConfigValues         $config  The Configuration of this node
         * @param IManagePersonalConfigValues $pconfig The personal/user configuration
         *
         * @throws HTTPException\InternalServerErrorException
         */
-       public function run(App $app, BaseURL $baseURL, Mode $mode, Module $module, L10n $l10n, Profiler $profiler, IManageConfigValues $config, IManagePersonalConfigValues $pconfig)
+       public function run(App $app, BaseURL $baseURL, Mode $mode, ModuleController $module, L10n $l10n, Profiler $profiler, IManageConfigValues $config, IManagePersonalConfigValues $pconfig)
        {
                $moduleName = $module->getName();
 
index ead125cff26138f1ef46458ba319f9c72808a38a..0c134f37b48cbf38c4b96cfc117469f6dc11707e 100644 (file)
@@ -99,11 +99,11 @@ abstract class DI
        }
 
        /**
-        * @return App\Module
+        * @return App\ModuleController
         */
        public static function module()
        {
-               return self::$dice->create(App\Module::class);
+               return self::$dice->create(App\ModuleController::class);
        }
 
        /**
index 57ef629bb255aa04f74365774d0471d3e3b247bb..28d26b4e7b6cc71f3c7a74fb4492353abf8557f4 100644 (file)
@@ -181,10 +181,10 @@ return [
                        ['determine', [$_SERVER, $_GET], Dice::CHAIN_CALL],
                ],
        ],
-       App\Module::class => [
-               'instanceOf' => App\Module::class,
+       App\ModuleController::class => [
+               'instanceOf' => App\ModuleController::class,
                'call' => [
-                       ['determineModule', [], Dice::CHAIN_CALL],
+                       ['determineName', [], Dice::CHAIN_CALL],
                ],
        ],
        \Friendica\Core\System::class => [
index 24371925b87d40513af314bbc9beb6bbe723463a..80e45d308f5a2632bc5c890fec7c06c1f9c02219 100644 (file)
@@ -23,7 +23,7 @@ namespace Friendica\Test\src\App;
 
 use Detection\MobileDetect;
 use Friendica\App\Mode;
-use Friendica\App\Module;
+use Friendica\App\ModuleController;
 use Friendica\Core\Config\ValueObject\Cache;
 use Friendica\Database\Database;
 use Friendica\Test\MockedTest;
@@ -204,7 +204,7 @@ class ModeTest extends MockedTest
        public function testIsBackendNotIsBackend()
        {
                $server       = [];
-               $module       = new Module();
+               $module       = new ModuleController();
                $mobileDetect = new MobileDetect();
 
                $mode = (new Mode())->determineRunMode(true, $module, $server, $mobileDetect);
@@ -218,7 +218,7 @@ class ModeTest extends MockedTest
        public function testIsBackendButIndex()
        {
                $server       = [];
-               $module       = new Module(Module::DEFAULT, null, true);
+               $module       = new ModuleController(ModuleController::DEFAULT, null, true);
                $mobileDetect = new MobileDetect();
 
                $mode = (new Mode())->determineRunMode(false, $module, $server, $mobileDetect);
@@ -232,7 +232,7 @@ class ModeTest extends MockedTest
        public function testIsNotBackend()
        {
                $server       = [];
-               $module       = new Module(Module::DEFAULT, null, false);
+               $module       = new ModuleController(ModuleController::DEFAULT, null, false);
                $mobileDetect = new MobileDetect();
 
                $mode = (new Mode())->determineRunMode(false, $module, $server, $mobileDetect);
@@ -250,7 +250,7 @@ class ModeTest extends MockedTest
                        'HTTP_X_REQUESTED_WITH' => 'xmlhttprequest',
                ];
 
-               $module       = new Module(Module::DEFAULT, null, false);
+               $module       = new ModuleController(ModuleController::DEFAULT, null, false);
                $mobileDetect = new MobileDetect();
 
                $mode = (new Mode())->determineRunMode(true, $module, $server, $mobileDetect);
@@ -264,7 +264,7 @@ class ModeTest extends MockedTest
        public function testIsNotAjax()
        {
                $server       = [];
-               $module       = new Module(Module::DEFAULT, null, false);
+               $module       = new ModuleController(ModuleController::DEFAULT, null, false);
                $mobileDetect = new MobileDetect();
 
                $mode = (new Mode())->determineRunMode(true, $module, $server, $mobileDetect);
@@ -278,7 +278,7 @@ class ModeTest extends MockedTest
        public function testIsMobileIsTablet()
        {
                $server       = [];
-               $module       = new Module(Module::DEFAULT, null, false);
+               $module       = new ModuleController(ModuleController::DEFAULT, null, false);
                $mobileDetect = Mockery::mock(MobileDetect::class);
                $mobileDetect->shouldReceive('isMobile')->andReturn(true);
                $mobileDetect->shouldReceive('isTablet')->andReturn(true);
@@ -296,7 +296,7 @@ class ModeTest extends MockedTest
        public function testIsNotMobileIsNotTablet()
        {
                $server       = [];
-               $module       = new Module(Module::DEFAULT, null, false);
+               $module       = new ModuleController(ModuleController::DEFAULT, null, false);
                $mobileDetect = Mockery::mock(MobileDetect::class);
                $mobileDetect->shouldReceive('isMobile')->andReturn(false);
                $mobileDetect->shouldReceive('isTablet')->andReturn(false);
index 8bcd81bc83f775d60f1eeea85de1d38bca525e03..52823fc136ab48a42b848fa13cdd3cc22e9f467b 100644 (file)
@@ -35,11 +35,11 @@ use Mockery;
 
 class ModuleTest extends DatabaseTest
 {
-       private function assertModule(array $assert, App\Module $module)
+       private function assertModule(array $assert, App\ModuleController $module)
        {
                self::assertEquals($assert['isBackend'], $module->isBackend());
                self::assertEquals($assert['name'], $module->getName());
-               self::assertEquals($assert['class'], $module->getClass());
+               self::assertEquals($assert['class'], $module->getModule());
        }
 
        /**
@@ -47,20 +47,20 @@ class ModuleTest extends DatabaseTest
         */
        public function testDefault()
        {
-               $module = new App\Module();
+               $module = new App\ModuleController();
 
-               $defaultClass = App\Module::DEFAULT_CLASS;
+               $defaultClass = App\ModuleController::DEFAULT_CLASS;
 
                self::assertModule([
                        'isBackend' => false,
-                       'name'      => App\Module::DEFAULT,
+                       'name'      => App\ModuleController::DEFAULT,
                        'class'     => new $defaultClass(),
                ], $module);
        }
 
        public function dataModuleName()
        {
-               $defaultClass = App\Module::DEFAULT_CLASS;
+               $defaultClass = App\ModuleController::DEFAULT_CLASS;
 
                return [
                        'default'                   => [
@@ -88,7 +88,7 @@ class ModuleTest extends DatabaseTest
                        'withNothing'               => [
                                'assert' => [
                                        'isBackend' => false,
-                                       'name'      => App\Module::DEFAULT,
+                                       'name'      => App\ModuleController::DEFAULT,
                                        'class'     => new $defaultClass(),
                                ],
                                'args'   => new App\Arguments(),
@@ -96,7 +96,7 @@ class ModuleTest extends DatabaseTest
                        'withIndex'                 => [
                                'assert' => [
                                        'isBackend' => false,
-                                       'name'      => App\Module::DEFAULT,
+                                       'name'      => App\ModuleController::DEFAULT,
                                        'class'     => new $defaultClass(),
                                ],
                                'args'   => new App\Arguments(),
@@ -104,12 +104,12 @@ class ModuleTest extends DatabaseTest
                        'withBackendMod'    => [
                                'assert' => [
                                        'isBackend' => true,
-                                       'name'      => App\Module::BACKEND_MODULES[0],
+                                       'name'      => App\ModuleController::BACKEND_MODULES[0],
                                        'class'     => new $defaultClass(),
                                ],
-                               'args'   => new App\Arguments(App\Module::BACKEND_MODULES[0] . '/data/in',
-                                       App\Module::BACKEND_MODULES[0] . '/data/in',
-                                       [App\Module::BACKEND_MODULES[0], 'data', 'in'],
+                               'args'   => new App\Arguments(App\ModuleController::BACKEND_MODULES[0] . '/data/in',
+                                       App\ModuleController::BACKEND_MODULES[0] . '/data/in',
+                                       [App\ModuleController::BACKEND_MODULES[0], 'data', 'in'],
                                        3),
                        ],
                        'withFirefoxApp'            => [
@@ -133,7 +133,7 @@ class ModuleTest extends DatabaseTest
         */
        public function testModuleName(array $assert, App\Arguments $args)
        {
-               $module = (new App\Module())->determineModule($args);
+               $module = (new App\ModuleController())->determineName($args);
 
                self::assertModule($assert, $module);
        }
@@ -142,9 +142,9 @@ class ModuleTest extends DatabaseTest
        {
                return [
                        'default' => [
-                               'assert'  => App\Module::DEFAULT_CLASS,
-                               'name'    => App\Module::DEFAULT,
-                               'command' => App\Module::DEFAULT,
+                               'assert'  => App\ModuleController::DEFAULT_CLASS,
+                               'name'    => App\ModuleController::DEFAULT,
+                               'command' => App\ModuleController::DEFAULT,
                                'privAdd' => false,
                                'args'    => [],
                        ],
@@ -200,9 +200,9 @@ class ModuleTest extends DatabaseTest
 
                $dice->shouldReceive('create')->andReturn(new $assert(...$args));
 
-               $module = (new App\Module($name))->determineClass(new App\Arguments('', $command), $router, $config, $dice);
+               $module = (new App\ModuleController($name))->determineClass(new App\Arguments('', $command), $router, $config, $dice);
 
-               self::assertEquals($assert, $module->getClass()->getClassName());
+               self::assertEquals($assert, $module->getModule()->getClassName());
        }
 
        /**
@@ -210,9 +210,9 @@ class ModuleTest extends DatabaseTest
         */
        public function testImmutable()
        {
-               $module = new App\Module();
+               $module = new App\ModuleController();
 
-               $moduleNew = $module->determineModule(new App\Arguments());
+               $moduleNew = $module->determineName(new App\Arguments());
 
                self::assertNotSame($moduleNew, $module);
        }