Browse Source

Revert "Introduce Arguments / Module class"

pull/7504/head
Hypolite Petovan 1 week ago
parent
commit
fcb1a78352
No account linked to committer's email address

+ 1
- 5
index.php View File

@@ -18,8 +18,4 @@ $dice = (new Dice())->addRules(include __DIR__ . '/static/dependencies.config.ph
18 18
 
19 19
 $a = \Friendica\BaseObject::getApp();
20 20
 
21
-$a->runFrontend(
22
-	$dice->create(\Friendica\App\Module::class),
23
-	$dice->create(\Friendica\App\Router::class),
24
-	$dice->create(\Friendica\Core\Config\PConfiguration::class)
25
-);
21
+$a->runFrontend();

+ 248
- 83
src/App.php View File

@@ -8,11 +8,9 @@ use Detection\MobileDetect;
8 8
 use DOMDocument;
9 9
 use DOMXPath;
10 10
 use Exception;
11
-use Friendica\App\Arguments;
12
-use Friendica\App\Module;
13 11
 use Friendica\Core\Config\Cache\ConfigCache;
14 12
 use Friendica\Core\Config\Configuration;
15
-use Friendica\Core\Config\PConfiguration;
13
+use Friendica\Core\Hook;
16 14
 use Friendica\Core\L10n\L10n;
17 15
 use Friendica\Core\System;
18 16
 use Friendica\Core\Theme;
@@ -20,7 +18,6 @@ use Friendica\Database\Database;
20 18
 use Friendica\Database\DBA;
21 19
 use Friendica\Model\Profile;
22 20
 use Friendica\Module\Login;
23
-use Friendica\Module\Special\HTTPException as ModuleHTTPException;
24 21
 use Friendica\Network\HTTPException;
25 22
 use Friendica\Util\BaseURL;
26 23
 use Friendica\Util\ConfigFileLoader;
@@ -44,7 +41,7 @@ use Psr\Log\LoggerInterface;
44 41
  */
45 42
 class App
46 43
 {
47
-	/** @deprecated 2019.09 - use App\Arguments->getQueryString() */
44
+	public $module_class = null;
48 45
 	public $query_string = '';
49 46
 	public $page = [];
50 47
 	public $profile;
@@ -56,13 +53,9 @@ class App
56 53
 	public $page_contact;
57 54
 	public $content;
58 55
 	public $data = [];
59
-	/** @deprecated 2019.09 - use App\Arguments->getCommand() */
60 56
 	public $cmd = '';
61
-	/** @deprecated 2019.09 - use App\Arguments->getArgv() or Arguments->get() */
62 57
 	public $argv;
63
-	/** @deprecated 2019.09 - use App\Arguments->getArgc() */
64 58
 	public $argc;
65
-	/** @deprecated 2019.09 - Use App\Module->getName() instead */
66 59
 	public $module;
67 60
 	public $timezone;
68 61
 	public $interactive = true;
@@ -100,8 +93,6 @@ class App
100 93
 
101 94
 	/**
102 95
 	 * @var bool true, if the call is from an backend node (f.e. worker)
103
-	 *
104
-	 * @deprecated 2019.09 - use App\Module->isBackend() instead
105 96
 	 */
106 97
 	private $isBackend;
107 98
 
@@ -145,16 +136,6 @@ class App
145 136
 	 */
146 137
 	private $l10n;
147 138
 
148
-	/**
149
-	 * @var App\Arguments
150
-	 */
151
-	private $args;
152
-
153
-	/**
154
-	 * @var App\Module
155
-	 */
156
-	private $moduleClass;
157
-
158 139
 	/**
159 140
 	 * Returns the current config cache of this node
160 141
 	 *
@@ -216,16 +197,6 @@ class App
216 197
 		return $this->mode;
217 198
 	}
218 199
 
219
-	/**
220
-	 * Returns the Database of the Application
221
-	 *
222
-	 * @return Database
223
-	 */
224
-	public function getDBA()
225
-	{
226
-		return $this->database;
227
-	}
228
-
229 200
 	/**
230 201
 	 * Register a stylesheet file path to be included in the <head> tag of every page.
231 202
 	 * Inclusion is done in App->initHead().
@@ -276,7 +247,7 @@ class App
276 247
 	 *
277 248
 	 * @throws Exception if the Basepath is not usable
278 249
 	 */
279
-	public function __construct(Database $database, Configuration $config, App\Mode $mode, App\Router $router, BaseURL $baseURL, LoggerInterface $logger, Profiler $profiler, L10n $l10n, Arguments $args, Module $module)
250
+	public function __construct(Database $database, Configuration $config, App\Mode $mode, App\Router $router, BaseURL $baseURL, LoggerInterface $logger, Profiler $profiler, L10n $l10n)
280 251
 	{
281 252
 		$this->database = $database;
282 253
 		$this->config   = $config;
@@ -286,8 +257,6 @@ class App
286 257
 		$this->profiler = $profiler;
287 258
 		$this->logger   = $logger;
288 259
 		$this->l10n     = $l10n;
289
-		$this->args = $args;
290
-		$this->isBackend = $module->isBackend();
291 260
 
292 261
 		$this->profiler->reset();
293 262
 
@@ -304,10 +273,59 @@ class App
304 273
 			. $this->getBasePath() . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
305 274
 			. $this->getBasePath());
306 275
 
307
-		$this->cmd = $args->getCommand();
308
-		$this->argv = $args->getArgv();
309
-		$this->argc = $args->getArgc();
310
-		$this->query_string = $args->getQueryString();
276
+		if (!empty($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], 'pagename=') === 0) {
277
+			$this->query_string = substr($_SERVER['QUERY_STRING'], 9);
278
+		} elseif (!empty($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], 'q=') === 0) {
279
+			$this->query_string = substr($_SERVER['QUERY_STRING'], 2);
280
+		}
281
+
282
+		// removing trailing / - maybe a nginx problem
283
+		$this->query_string = ltrim($this->query_string, '/');
284
+
285
+		if (!empty($_GET['pagename'])) {
286
+			$this->cmd = trim($_GET['pagename'], '/\\');
287
+		} elseif (!empty($_GET['q'])) {
288
+			$this->cmd = trim($_GET['q'], '/\\');
289
+		}
290
+
291
+		// fix query_string
292
+		$this->query_string = str_replace($this->cmd . '&', $this->cmd . '?', $this->query_string);
293
+
294
+		// unix style "homedir"
295
+		if (substr($this->cmd, 0, 1) === '~') {
296
+			$this->cmd = 'profile/' . substr($this->cmd, 1);
297
+		}
298
+
299
+		// Diaspora style profile url
300
+		if (substr($this->cmd, 0, 2) === 'u/') {
301
+			$this->cmd = 'profile/' . substr($this->cmd, 2);
302
+		}
303
+
304
+		/*
305
+		 * Break the URL path into C style argc/argv style arguments for our
306
+		 * modules. Given "http://example.com/module/arg1/arg2", $this->argc
307
+		 * will be 3 (integer) and $this->argv will contain:
308
+		 *   [0] => 'module'
309
+		 *   [1] => 'arg1'
310
+		 *   [2] => 'arg2'
311
+		 *
312
+		 *
313
+		 * There will always be one argument. If provided a naked domain
314
+		 * URL, $this->argv[0] is set to "home".
315
+		 */
316
+
317
+		$this->argv = explode('/', $this->cmd);
318
+		$this->argc = count($this->argv);
319
+		if ((array_key_exists('0', $this->argv)) && strlen($this->argv[0])) {
320
+			$this->module = str_replace('.', '_', $this->argv[0]);
321
+			$this->module = str_replace('-', '_', $this->module);
322
+		} else {
323
+			$this->argc = 1;
324
+			$this->argv = ['home'];
325
+			$this->module = 'home';
326
+		}
327
+
328
+		$this->isBackend = $this->isBackend || $this->checkBackend($this->module);
311 329
 
312 330
 		// Detect mobile devices
313 331
 		$mobile_detect = new MobileDetect();
@@ -328,6 +346,10 @@ class App
328 346
 	 */
329 347
 	public function reload()
330 348
 	{
349
+		$this->isBackend = basename($_SERVER['PHP_SELF'], '.php') !== 'index';
350
+
351
+		$this->getMode()->determine($this->getBasePath());
352
+
331 353
 		if ($this->getMode()->has(App\Mode::DBAVAILABLE)) {
332 354
 			$this->profiler->update($this->config);
333 355
 
@@ -377,8 +399,6 @@ class App
377 399
 	 * @param bool $ssl Whether to append http or https under BaseURL::SSL_POLICY_SELFSIGN
378 400
 	 *
379 401
 	 * @return string Friendica server base URL
380
-	 *
381
-	 * @deprecated 2019.09 - use BaseUrl->get($ssl) instead
382 402
 	 */
383 403
 	public function getBaseURL($ssl = false)
384 404
 	{
@@ -433,9 +453,9 @@ class App
433 453
 	 * - Infinite scroll data
434 454
 	 * - head.tpl template
435 455
 	 */
436
-	private function initHead(App\Module $module, PConfiguration $pconfig)
456
+	public function initHead()
437 457
 	{
438
-		$interval = ((local_user()) ? $pconfig->get(local_user(), 'system', 'update_interval') : 40000);
458
+		$interval = ((local_user()) ? Core\PConfig::get(local_user(), 'system', 'update_interval') : 40000);
439 459
 
440 460
 		// If the update is 'deactivated' set it to the highest integer number (~24 days)
441 461
 		if ($interval < 0) {
@@ -447,8 +467,8 @@ class App
447 467
 		}
448 468
 
449 469
 		// Default title: current module called
450
-		if (empty($this->page['title']) && $module->getName()) {
451
-			$this->page['title'] = ucfirst($module->getName());
470
+		if (empty($this->page['title']) && $this->module) {
471
+			$this->page['title'] = ucfirst($this->module);
452 472
 		}
453 473
 
454 474
 		// Prepend the sitename to the page title
@@ -500,7 +520,7 @@ class App
500 520
 	 * - Registered footer scripts (through App->registerFooterScript())
501 521
 	 * - footer.tpl template
502 522
 	 */
503
-	private function initFooter()
523
+	public function initFooter()
504 524
 	{
505 525
 		// If you're just visiting, let javascript take you home
506 526
 		if (!empty($_SESSION['visitor_home'])) {
@@ -575,6 +595,58 @@ class App
575 595
 			$this->getBaseURL();
576 596
 	}
577 597
 
598
+	/**
599
+	 * @brief Checks if the site is called via a backend process
600
+	 *
601
+	 * This isn't a perfect solution. But we need this check very early.
602
+	 * So we cannot wait until the modules are loaded.
603
+	 *
604
+	 * @param string $module
605
+	 * @return bool
606
+	 */
607
+	private function checkBackend($module) {
608
+		static $backends = [
609
+			'_well_known',
610
+			'api',
611
+			'dfrn_notify',
612
+			'feed',
613
+			'fetch',
614
+			'followers',
615
+			'following',
616
+			'hcard',
617
+			'hostxrd',
618
+			'inbox',
619
+			'manifest',
620
+			'nodeinfo',
621
+			'noscrape',
622
+			'objects',
623
+			'outbox',
624
+			'poco',
625
+			'post',
626
+			'proxy',
627
+			'pubsub',
628
+			'pubsubhubbub',
629
+			'receive',
630
+			'rsd_xml',
631
+			'salmon',
632
+			'statistics_json',
633
+			'xrd',
634
+		];
635
+
636
+		// Check if current module is in backend or backend flag is set
637
+		return in_array($module, $backends);
638
+	}
639
+
640
+	/**
641
+	 * Returns true, if the call is from a backend node (f.e. from a worker)
642
+	 *
643
+	 * @return bool Is it a known backend?
644
+	 */
645
+	public function isBackend()
646
+	{
647
+		return $this->isBackend;
648
+	}
649
+
578 650
 	/**
579 651
 	 * @brief Checks if the maximum number of database processes is reached
580 652
 	 *
@@ -668,7 +740,7 @@ class App
668 740
 	 */
669 741
 	public function isMaxLoadReached()
670 742
 	{
671
-		if ($this->isBackend) {
743
+		if ($this->isBackend()) {
672 744
 			$process = 'backend';
673 745
 			$maxsysload = intval($this->config->get('system', 'maxloadavg'));
674 746
 			if ($maxsysload < 1) {
@@ -858,13 +930,21 @@ class App
858 930
 	}
859 931
 
860 932
 	/**
861
-	 * @deprecated use Arguments->get() instead
933
+	 * Returns the value of a argv key
934
+	 * TODO there are a lot of $a->argv usages in combination with defaults() which can be replaced with this method
935
+	 *
936
+	 * @param int $position the position of the argument
937
+	 * @param mixed $default the default value if not found
862 938
 	 *
863
-	 * @see App\Arguments
939
+	 * @return mixed returns the value of the argument
864 940
 	 */
865 941
 	public function getArgumentValue($position, $default = '')
866 942
 	{
867
-		return $this->args->get($position, $default);
943
+		if (array_key_exists($position, $this->argv)) {
944
+			return $this->argv[$position];
945
+		}
946
+
947
+		return $default;
868 948
 	}
869 949
 
870 950
 	/**
@@ -893,13 +973,9 @@ class App
893 973
 	 * request and a representation of the response.
894 974
 	 *
895 975
 	 * This probably should change to limit the size of this monster method.
896
-	 *
897
-	 * @param App\Module $module The determined module
898 976
 	 */
899
-	public function runFrontend(App\Module $module, App\Router $router, PConfiguration $pconfig)
977
+	public function runFrontend()
900 978
 	{
901
-		$moduleName = $module->getName();
902
-
903 979
 		try {
904 980
 			// Missing DB connection: ERROR
905 981
 			if ($this->getMode()->has(App\Mode::LOCALCONFIGPRESENT) && !$this->getMode()->has(App\Mode::DBAVAILABLE)) {
@@ -909,7 +985,7 @@ class App
909 985
 			// Max Load Average reached: ERROR
910 986
 			if ($this->isMaxProcessesReached() || $this->isMaxLoadReached()) {
911 987
 				header('Retry-After: 120');
912
-				header('Refresh: 120; url=' . $this->baseURL->get() . "/" . $this->args->getQueryString());
988
+				header('Refresh: 120; url=' . $this->getBaseURL() . "/" . $this->query_string);
913 989
 
914 990
 				throw new HTTPException\ServiceUnavailableException('The node is currently overloaded. Please try again later.');
915 991
 			}
@@ -917,7 +993,7 @@ class App
917 993
 			if (!$this->getMode()->isInstall()) {
918 994
 				// Force SSL redirection
919 995
 				if ($this->baseURL->checkRedirectHttps()) {
920
-					System::externalRedirect($this->baseURL->get() . '/' . $this->args->getQueryString());
996
+					System::externalRedirect($this->getBaseURL() . '/' . $this->query_string);
921 997
 				}
922 998
 
923 999
 				Core\Session::init();
@@ -925,7 +1001,7 @@ class App
925 1001
 			}
926 1002
 
927 1003
 			// Exclude the backend processes from the session management
928
-			if (!$module->isBackend()) {
1004
+			if (!$this->isBackend()) {
929 1005
 				$stamp1 = microtime(true);
930 1006
 				session_start();
931 1007
 				$this->profiler->saveTimestamp($stamp1, 'parser', Core\System::callstack());
@@ -945,6 +1021,7 @@ class App
945 1021
 
946 1022
 			// ZRL
947 1023
 			if (!empty($_GET['zrl']) && $this->getMode()->isNormal()) {
1024
+				$this->query_string = Model\Profile::stripZrls($this->query_string);
948 1025
 				if (!local_user()) {
949 1026
 					// Only continue when the given profile link seems valid
950 1027
 					// Valid profile links contain a path with "/profile/" and no query parameters
@@ -967,10 +1044,11 @@ class App
967 1044
 
968 1045
 			if (!empty($_GET['owt']) && $this->getMode()->isNormal()) {
969 1046
 				$token = $_GET['owt'];
1047
+				$this->query_string = Model\Profile::stripQueryParam($this->query_string, 'owt');
970 1048
 				Model\Profile::openWebAuthInit($token);
971 1049
 			}
972 1050
 
973
-			Login::sessionAuth();
1051
+			Module\Login::sessionAuth();
974 1052
 
975 1053
 			if (empty($_SESSION['authenticated'])) {
976 1054
 				header('X-Account-Management-Status: none');
@@ -988,9 +1066,9 @@ class App
988 1066
 
989 1067
 			// in install mode, any url loads install module
990 1068
 			// but we need "view" module for stylesheet
991
-			if ($this->getMode()->isInstall() && $moduleName !== 'install') {
1069
+			if ($this->getMode()->isInstall() && $this->module !== 'install') {
992 1070
 				$this->internalRedirect('install');
993
-			} elseif (!$this->getMode()->isInstall() && !$this->getMode()->has(App\Mode::MAINTENANCEDISABLED) && $moduleName !== 'maintenance') {
1071
+			} elseif (!$this->getMode()->isInstall() && !$this->getMode()->has(App\Mode::MAINTENANCEDISABLED) && $this->module !== 'maintenance') {
994 1072
 				$this->internalRedirect('maintenance');
995 1073
 			} else {
996 1074
 				$this->checkURL();
@@ -1013,65 +1091,152 @@ class App
1013 1091
 			];
1014 1092
 
1015 1093
 			// Compatibility with the Android Diaspora client
1016
-			if ($moduleName == 'stream') {
1094
+			if ($this->module == 'stream') {
1017 1095
 				$this->internalRedirect('network?order=post');
1018 1096
 			}
1019 1097
 
1020
-			if ($moduleName == 'conversations') {
1098
+			if ($this->module == 'conversations') {
1021 1099
 				$this->internalRedirect('message');
1022 1100
 			}
1023 1101
 
1024
-			if ($moduleName == 'commented') {
1102
+			if ($this->module == 'commented') {
1025 1103
 				$this->internalRedirect('network?order=comment');
1026 1104
 			}
1027 1105
 
1028
-			if ($moduleName == 'liked') {
1106
+			if ($this->module == 'liked') {
1029 1107
 				$this->internalRedirect('network?order=comment');
1030 1108
 			}
1031 1109
 
1032
-			if ($moduleName == 'activity') {
1110
+			if ($this->module == 'activity') {
1033 1111
 				$this->internalRedirect('network?conv=1');
1034 1112
 			}
1035 1113
 
1036
-			if (($moduleName == 'status_messages') && ($this->args->getCommand() == 'status_messages/new')) {
1114
+			if (($this->module == 'status_messages') && ($this->cmd == 'status_messages/new')) {
1037 1115
 				$this->internalRedirect('bookmarklet');
1038 1116
 			}
1039 1117
 
1040
-			if (($moduleName == 'user') && ($this->args->getCommand() == 'user/edit')) {
1118
+			if (($this->module == 'user') && ($this->cmd == 'user/edit')) {
1041 1119
 				$this->internalRedirect('settings');
1042 1120
 			}
1043 1121
 
1044
-			if (($moduleName == 'tag_followings') && ($this->args->getCommand() == 'tag_followings/manage')) {
1122
+			if (($this->module == 'tag_followings') && ($this->cmd == 'tag_followings/manage')) {
1045 1123
 				$this->internalRedirect('search');
1046 1124
 			}
1047 1125
 
1126
+			// Compatibility with the Firefox App
1127
+			if (($this->module == "users") && ($this->cmd == "users/sign_in")) {
1128
+				$this->module = "login";
1129
+			}
1130
+
1131
+			/*
1132
+			 * ROUTING
1133
+			 *
1134
+			 * From the request URL, routing consists of obtaining the name of a BaseModule-extending class of which the
1135
+			 * post() and/or content() static methods can be respectively called to produce a data change or an output.
1136
+			 */
1137
+
1138
+			// First we try explicit routes defined in App\Router
1139
+			$this->router->collectRoutes();
1140
+
1141
+			$data = $this->router->getRouteCollector();
1142
+			Hook::callAll('route_collection', $data);
1143
+
1144
+			$this->module_class = $this->router->getModuleClass($this->cmd);
1145
+
1146
+			// Then we try addon-provided modules that we wrap in the LegacyModule class
1147
+			if (!$this->module_class && Core\Addon::isEnabled($this->module) && file_exists("addon/{$this->module}/{$this->module}.php")) {
1148
+				//Check if module is an app and if public access to apps is allowed or not
1149
+				$privateapps = $this->config->get('config', 'private_addons', false);
1150
+				if ((!local_user()) && Core\Hook::isAddonApp($this->module) && $privateapps) {
1151
+					info($this->l10n->t("You must be logged in to use addons. "));
1152
+				} else {
1153
+					include_once "addon/{$this->module}/{$this->module}.php";
1154
+					if (function_exists($this->module . '_module')) {
1155
+						LegacyModule::setModuleFile("addon/{$this->module}/{$this->module}.php");
1156
+						$this->module_class = LegacyModule::class;
1157
+					}
1158
+				}
1159
+			}
1160
+
1161
+			/* Finally, we look for a 'standard' program module in the 'mod' directory
1162
+			 * We emulate a Module class through the LegacyModule class
1163
+			 */
1164
+			if (!$this->module_class && file_exists("mod/{$this->module}.php")) {
1165
+				LegacyModule::setModuleFile("mod/{$this->module}.php");
1166
+				$this->module_class = LegacyModule::class;
1167
+			}
1168
+
1169
+			/* The URL provided does not resolve to a valid module.
1170
+			 *
1171
+			 * On Dreamhost sites, quite often things go wrong for no apparent reason and they send us to '/internal_error.html'.
1172
+			 * We don't like doing this, but as it occasionally accounts for 10-20% or more of all site traffic -
1173
+			 * 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
1174
+			 * this will often succeed and eventually do the right thing.
1175
+			 *
1176
+			 * Otherwise we are going to emit a 404 not found.
1177
+			 */
1178
+			if (!$this->module_class) {
1179
+				// Stupid browser tried to pre-fetch our Javascript img template. Don't log the event or return anything - just quietly exit.
1180
+				if (!empty($_SERVER['QUERY_STRING']) && preg_match('/{[0-9]}/', $_SERVER['QUERY_STRING']) !== 0) {
1181
+					exit();
1182
+				}
1183
+
1184
+				if (!empty($_SERVER['QUERY_STRING']) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
1185
+					Core\Logger::log('index.php: dreamhost_error_hack invoked. Original URI =' . $_SERVER['REQUEST_URI']);
1186
+					$this->internalRedirect($_SERVER['REQUEST_URI']);
1187
+				}
1188
+
1189
+				Core\Logger::log('index.php: page not found: ' . $_SERVER['REQUEST_URI'] . ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: ' . $_SERVER['QUERY_STRING'], Core\Logger::DEBUG);
1190
+
1191
+				$this->module_class = Module\PageNotFound::class;
1192
+			}
1193
+
1048 1194
 			// Initialize module that can set the current theme in the init() method, either directly or via App->profile_uid
1049
-			$this->page['page_title'] = $moduleName;
1195
+			$this->page['page_title'] = $this->module;
1196
+
1197
+			$placeholder = '';
1198
+
1199
+			Core\Hook::callAll($this->module . '_mod_init', $placeholder);
1200
+
1201
+			call_user_func([$this->module_class, 'init']);
1202
+
1203
+			// "rawContent" is especially meant for technical endpoints.
1204
+			// This endpoint doesn't need any theme initialization or other comparable stuff.
1205
+			call_user_func([$this->module_class, 'rawContent']);
1050 1206
 
1051
-			// determine the module class and save it to the module instance
1052
-			// @todo there's an implicit dependency due SESSION::start(), so it has to be called here (yet)
1053
-			$module = $module->determineClass($this->args, $router, $this->config);
1207
+			// Load current theme info after module has been initialized as theme could have been set in module
1208
+			$theme_info_file = 'view/theme/' . $this->getCurrentTheme() . '/theme.php';
1209
+			if (file_exists($theme_info_file)) {
1210
+				require_once $theme_info_file;
1211
+			}
1054 1212
 
1055
-			// Let the module run it's internal process (init, get, post, ...)
1056
-			$module->run($this->l10n, $this, $this->logger, $this->getCurrentTheme(), $_SERVER, $_POST);
1213
+			if (function_exists(str_replace('-', '_', $this->getCurrentTheme()) . '_init')) {
1214
+				$func = str_replace('-', '_', $this->getCurrentTheme()) . '_init';
1215
+				$func($this);
1216
+			}
1057 1217
 
1218
+			if ($_SERVER['REQUEST_METHOD'] === 'POST') {
1219
+				Core\Hook::callAll($this->module . '_mod_post', $_POST);
1220
+				call_user_func([$this->module_class, 'post']);
1221
+			}
1222
+
1223
+			Core\Hook::callAll($this->module . '_mod_afterpost', $placeholder);
1224
+			call_user_func([$this->module_class, 'afterpost']);
1058 1225
 		} catch(HTTPException $e) {
1059
-			ModuleHTTPException::rawContent($e);
1226
+			Module\Special\HTTPException::rawContent($e);
1060 1227
 		}
1061 1228
 
1062 1229
 		$content = '';
1063 1230
 
1064 1231
 		try {
1065
-			$moduleClass = $module->getClassName();
1066
-
1067 1232
 			$arr = ['content' => $content];
1068
-			Core\Hook::callAll($moduleClass . '_mod_content', $arr);
1233
+			Core\Hook::callAll($this->module . '_mod_content', $arr);
1069 1234
 			$content = $arr['content'];
1070
-			$arr = ['content' => call_user_func([$moduleClass, 'content'])];
1071
-			Core\Hook::callAll($moduleClass . '_mod_aftercontent', $arr);
1235
+			$arr = ['content' => call_user_func([$this->module_class, 'content'])];
1236
+			Core\Hook::callAll($this->module . '_mod_aftercontent', $arr);
1072 1237
 			$content .= $arr['content'];
1073 1238
 		} catch(HTTPException $e) {
1074
-			$content = ModuleHTTPException::content($e);
1239
+			$content = Module\Special\HTTPException::content($e);
1075 1240
 		}
1076 1241
 
1077 1242
 		// initialise content region
@@ -1088,7 +1253,7 @@ class App
1088 1253
 		 * all the module functions have executed so that all
1089 1254
 		 * theme choices made by the modules can take effect.
1090 1255
 		 */
1091
-		$this->initHead($module, $pconfig);
1256
+		$this->initHead();
1092 1257
 
1093 1258
 		/* Build the page ending -- this is stuff that goes right before
1094 1259
 		 * the closing </body> tag
@@ -1100,7 +1265,7 @@ class App
1100 1265
 		}
1101 1266
 
1102 1267
 		// Add the navigation (menu) template
1103
-		if ($moduleName != 'install' && $moduleName != 'maintenance') {
1268
+		if ($this->module != 'install' && $this->module != 'maintenance') {
1104 1269
 			$this->page['htmlhead'] .= Core\Renderer::replaceMacros(Core\Renderer::getMarkupTemplate('nav_head.tpl'), []);
1105 1270
 			$this->page['nav']       = Content\Nav::build($this);
1106 1271
 		}

+ 0
- 194
src/App/Arguments.php View File

@@ -1,194 +0,0 @@
1
-<?php
2
-
3
-namespace Friendica\App;
4
-
5
-/**
6
- * Determine all arguments of the current call, including
7
- * - The whole querystring (except the pagename/q parameter)
8
- * - The command
9
- * - The arguments (C-Style based)
10
- * - The count of arguments
11
- */
12
-class Arguments
13
-{
14
-	/**
15
-	 * @var string The complete query string
16
-	 */
17
-	private $queryString;
18
-	/**
19
-	 * @var string The current Friendica command
20
-	 */
21
-	private $command;
22
-	/**
23
-	 * @var array The arguments of the current execution
24
-	 */
25
-	private $argv;
26
-	/**
27
-	 * @var int The count of arguments
28
-	 */
29
-	private $argc;
30
-
31
-	public function __construct(string $queryString = '', string $command = '', array $argv = [Module::DEFAULT], int $argc = 1)
32
-	{
33
-		$this->queryString = $queryString;
34
-		$this->command     = $command;
35
-		$this->argv        = $argv;
36
-		$this->argc        = $argc;
37
-	}
38
-
39
-	/**
40
-	 * @return string The whole query string of this call
41
-	 */
42
-	public function getQueryString()
43
-	{
44
-		return $this->queryString;
45
-	}
46
-
47
-	/**
48
-	 * @return string The whole command of this call
49
-	 */
50
-	public function getCommand()
51
-	{
52
-		return $this->command;
53
-	}
54
-
55
-	/**
56
-	 * @return array All arguments of this call
57
-	 */
58
-	public function getArgv()
59
-	{
60
-		return $this->argv;
61
-	}
62
-
63
-	/**
64
-	 * @return int The count of arguments of this call
65
-	 */
66
-	public function getArgc()
67
-	{
68
-		return $this->argc;
69
-	}
70
-
71
-	/**
72
-	 * Returns the value of a argv key
73
-	 * @todo there are a lot of $a->argv usages in combination with defaults() which can be replaced with this method
74
-	 *
75
-	 * @param int   $position the position of the argument
76
-	 * @param mixed $default  the default value if not found
77
-	 *
78
-	 * @return mixed returns the value of the argument
79
-	 */
80
-	public function get(int $position, $default = '')
81
-	{
82
-		return $this->has($position) ? $this->argv[$position] : $default;
83
-	}
84
-
85
-	/**
86
-	 * @param int $position
87
-	 *
88
-	 * @return bool if the argument position exists
89
-	 */
90
-	public function has(int $position)
91
-	{
92
-		return array_key_exists($position, $this->argv);
93
-	}
94
-
95
-	/**
96
-	 * Determine the arguments of the current call
97
-	 *
98
-	 * @param array $server The $_SERVER variable
99
-	 * @param array $get    The $_GET variable
100
-	 *
101
-	 * @return Arguments The determined arguments
102
-	 */
103
-	public function determine(array $server, array $get)
104
-	{
105
-		$queryString = '';
106
-
107
-		if (!empty($server['QUERY_STRING']) && strpos($server['QUERY_STRING'], 'pagename=') === 0) {
108
-			$queryString = substr($server['QUERY_STRING'], 9);
109
-		} elseif (!empty($server['QUERY_STRING']) && strpos($server['QUERY_STRING'], 'q=') === 0) {
110
-			$queryString = substr($server['QUERY_STRING'], 2);
111
-		}
112
-
113
-		// eventually strip ZRL
114
-		$queryString = $this->stripZRLs($queryString);
115
-
116
-		// eventually strip OWT
117
-		$queryString = $this->stripQueryParam($queryString, 'owt');
118
-
119
-		// removing trailing / - maybe a nginx problem
120
-		$queryString = ltrim($queryString, '/');
121
-
122
-		if (!empty($get['pagename'])) {
123
-			$command = trim($get['pagename'], '/\\');
124
-		} elseif (!empty($get['q'])) {
125
-			$command = trim($get['q'], '/\\');
126
-		} else {
127
-			$command = Module::DEFAULT;
128
-		}
129
-
130
-
131
-		// fix query_string
132
-		if (!empty($command)) {
133
-			$queryString = str_replace(
134
-				$command . '&',
135
-				$command . '?',
136
-				$queryString
137
-			);
138
-		}
139
-
140
-		// unix style "homedir"
141
-		if (substr($command, 0, 1) === '~') {
142
-			$command = 'profile/' . substr($command, 1);
143
-		}
144
-
145
-		// Diaspora style profile url
146
-		if (substr($command, 0, 2) === 'u/') {
147
-			$command = 'profile/' . substr($command, 2);
148
-		}
149
-
150
-		/*
151
-		 * Break the URL path into C style argc/argv style arguments for our
152
-		 * modules. Given "http://example.com/module/arg1/arg2", $this->argc
153
-		 * will be 3 (integer) and $this->argv will contain:
154
-		 *   [0] => 'module'
155
-		 *   [1] => 'arg1'
156
-		 *   [2] => 'arg2'
157
-		 *
158
-		 *
159
-		 * There will always be one argument. If provided a naked domain
160
-		 * URL, $this->argv[0] is set to "home".
161
-		 */
162
-
163
-		$argv = explode('/', $command);
164
-		$argc = count($argv);
165
-
166
-
167
-		return new Arguments($queryString, $command, $argv, $argc);
168
-	}
169
-
170
-	/**
171
-	 * Strip zrl parameter from a string.
172
-	 *
173
-	 * @param string $queryString The input string.
174
-	 *
175
-	 * @return string The zrl.
176
-	 */
177
-	public function stripZRLs(string $queryString)
178
-	{
179
-		return preg_replace('/[?&]zrl=(.*?)(&|$)/ism', '$2', $queryString);
180
-	}
181
-
182
-	/**
183
-	 * Strip query parameter from a string.
184
-	 *
185
-	 * @param string $queryString The input string.
186
-	 * @param string $param
187
-	 *
188
-	 * @return string The query parameter.
189
-	 */
190
-	public function stripQueryParam(string $queryString, string $param)
191
-	{
192
-		return preg_replace('/[?&]' . $param . '=(.*?)(&|$)/ism', '$2', $queryString);
193
-	}
194
-}

+ 44
- 22
src/App/Mode.php View File

@@ -24,9 +24,27 @@ class Mode
24 24
 	 */
25 25
 	private $mode;
26 26
 
27
-	public function __construct(int $mode = 0)
27
+	/**
28
+	 * @var string the basepath of the application
29
+	 */
30
+	private $basepath;
31
+
32
+	/**
33
+	 * @var Database
34
+	 */
35
+	private $database;
36
+
37
+	/**
38
+	 * @var ConfigCache
39
+	 */
40
+	private $configCache;
41
+
42
+	public function __construct(BasePath $basepath, Database $database, ConfigCache $configCache)
28 43
 	{
29
-		$this->mode = $mode;
44
+		$this->basepath    = $basepath->getPath();
45
+		$this->database    = $database;
46
+		$this->configCache = $configCache;
47
+		$this->mode        = 0;
30 48
 	}
31 49
 
32 50
 	/**
@@ -36,46 +54,50 @@ class Mode
36 54
 	 * - App::MODE_MAINTENANCE: The maintenance mode has been set
37 55
 	 * - App::MODE_NORMAL     : Normal run with all features enabled
38 56
 	 *
39
-	 * @return Mode returns the determined mode
57
+	 * @param string $basePath the Basepath of the Application
58
+	 *
59
+	 * @return Mode returns itself
40 60
 	 *
41 61
 	 * @throws \Exception
42 62
 	 */
43
-	public function determine(BasePath $basepath, Database $database, ConfigCache $configCache)
63
+	public function determine($basePath = null)
44 64
 	{
45
-		$mode = 0;
65
+		if (!empty($basePath)) {
66
+			$this->basepath = $basePath;
67
+		}
46 68
 
47
-		$basepathName = $basepath->getPath();
69
+		$this->mode = 0;
48 70
 
49
-		if (!file_exists($basepathName . '/config/local.config.php')
50
-		    && !file_exists($basepathName . '/config/local.ini.php')
51
-		    && !file_exists($basepathName . '/.htconfig.php')) {
52
-			return new Mode($mode);
71
+		if (!file_exists($this->basepath . '/config/local.config.php')
72
+		    && !file_exists($this->basepath . '/config/local.ini.php')
73
+		    && !file_exists($this->basepath . '/.htconfig.php')) {
74
+			return $this;
53 75
 		}
54 76
 
55
-		$mode |= Mode::LOCALCONFIGPRESENT;
77
+		$this->mode |= Mode::LOCALCONFIGPRESENT;
56 78
 
57
-		if (!$database->connected()) {
58
-			return new Mode($mode);
79
+		if (!$this->database->connected()) {
80
+			return $this;
59 81
 		}
60 82
 
61
-		$mode |= Mode::DBAVAILABLE;
83
+		$this->mode |= Mode::DBAVAILABLE;
62 84
 
63
-		if ($database->fetchFirst("SHOW TABLES LIKE 'config'") === false) {
64
-			return new Mode($mode);
85
+		if ($this->database->fetchFirst("SHOW TABLES LIKE 'config'") === false) {
86
+			return $this;
65 87
 		}
66 88
 
67
-		$mode |= Mode::DBCONFIGAVAILABLE;
89
+		$this->mode |= Mode::DBCONFIGAVAILABLE;
68 90
 
69
-		if (!empty($configCache->get('system', 'maintenance')) ||
91
+		if (!empty($this->configCache->get('system', 'maintenance')) ||
70 92
 		    // Don't use Config or Configuration here because we're possibly BEFORE initializing the Configuration,
71 93
 		    // so this could lead to a dependency circle
72
-		    !empty($database->selectFirst('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])['v'])) {
73
-			return new Mode($mode);
94
+		    !empty($this->database->selectFirst('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])['v'])) {
95
+			return $this;
74 96
 		}
75 97
 
76
-		$mode |= Mode::MAINTENANCEDISABLED;
98
+		$this->mode |= Mode::MAINTENANCEDISABLED;
77 99
 
78
-		return new Mode($mode);
100
+		return $this;
79 101
 	}
80 102
 
81 103
 	/**

+ 0
- 279
src/App/Module.php View File

@@ -1,279 +0,0 @@
1
-<?php
2
-
3
-namespace Friendica\App;
4
-
5
-use Friendica\App;
6
-use Friendica\BaseObject;
7
-use Friendica\Core;
8
-use Friendica\LegacyModule;
9
-use Friendica\Module\Home;
10
-use Friendica\Module\PageNotFound;
11
-use Psr\Log\LoggerInterface;
12
-
13
-/**
14
- * Holds the common context of the current, loaded module
15
- */
16
-class Module
17
-{
18
-	const DEFAULT = 'home';
19
-	const DEFAULT_CLASS = Home::class;
20
-	/**
21
-	 * A list of modules, which are backend methods
22
-	 *
23
-	 * @var array
24
-	 */
25
-	const BACKEND_MODULES = [
26
-		'_well_known',
27
-		'api',
28
-		'dfrn_notify',
29
-		'feed',
30
-		'fetch',
31
-		'followers',
32
-		'following',
33
-		'hcard',
34
-		'hostxrd',
35
-		'inbox',
36
-		'manifest',
37
-		'nodeinfo',
38
-		'noscrape',
39
-		'objects',
40
-		'outbox',
41
-		'poco',
42
-		'post',
43
-		'proxy',
44
-		'pubsub',
45
-		'pubsubhubbub',
46
-		'receive',
47
-		'rsd_xml',
48
-		'salmon',
49
-		'statistics_json',
50
-		'xrd',
51
-	];
52
-
53
-	/**
54
-	 * @var string The module name
55
-	 */
56
-	private $module;
57
-
58
-	/**
59
-	 * @var BaseObject The module class
60
-	 */
61
-	private $module_class;
62
-
63
-	/**
64
-	 * @var bool true, if the module is a backend module
65
-	 */
66
-	private $isBackend;
67
-
68
-	/**
69
-	 * @var bool true, if the loaded addon is private, so we have to print out not allowed
70
-	 */
71
-	private $printNotAllowedAddon;
72
-
73
-	/**
74
-	 * @return string
75
-	 */
76
-	public function getName()
77
-	{
78
-		return $this->module;
79
-	}
80
-
81
-	/**
82
-	 * @return string The base class name
83
-	 */
84
-	public function getClassName()
85
-	{
86
-		return $this->module_class;
87
-	}
88
-
89
-	/**
90
-	 * @return bool
91
-	 */
92
-	public function isBackend()
93
-	{
94
-		return $this->isBackend;
95
-	}
96
-
97
-	public function __construct(string $module = self::DEFAULT, string $moduleClass = self::DEFAULT_CLASS, bool $isBackend = false, bool $printNotAllowedAddon = false)
98
-	{
99
-		$this->module       = $module;
100
-		$this->module_class = $moduleClass;
101
-		$this->isBackend    = $isBackend;
102
-		$this->printNotAllowedAddon = $printNotAllowedAddon;
103
-	}
104
-
105
-	/**
106
-	 * Determines the current module based on the App arguments and the server variable
107
-	 *
108
-	 * @param Arguments $args   The Friendica arguments
109
-	 * @param array     $server The $_SERVER variable
110
-	 *
111
-	 * @return Module The module with the determined module
112
-	 */
113
-	public function determineModule(Arguments $args, array $server)
114
-	{
115
-		if ($args->getArgc() > 0) {
116
-			$module = str_replace('.', '_', $args->get(0));
117
-			$module = str_replace('-', '_', $module);
118
-		} else {
119
-			$module = self::DEFAULT;
120
-		}
121
-
122
-		// Compatibility with the Firefox App
123
-		if (($module == "users") && ($args->getCommand() == "users/sign_in")) {
124
-			$module = "login";
125
-		}
126
-
127
-		$isBackend = $this->checkBackend($module, $server);
128
-
129
-		return new Module($module, $this->module_class, $isBackend, $this->printNotAllowedAddon);
130
-	}
131
-
132
-	/**
133
-	 * Determine the class of the current module
134
-	 *
135
-	 * @param Arguments                 $args   The Friendica execution arguments
136
-	 * @param Router                    $router The Friendica routing instance
137
-	 * @param Core\Config\Configuration $config The Friendica Configuration
138
-	 *
139
-	 * @return Module The determined module of this call
140
-	 *
141
-	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
142
-	 */
143
-	public function determineClass(Arguments $args, Router $router, Core\Config\Configuration $config)
144
-	{
145
-		$printNotAllowedAddon = false;
146
-
147
-		/**
148
-		 * ROUTING
149
-		 *
150
-		 * From the request URL, routing consists of obtaining the name of a BaseModule-extending class of which the
151
-		 * post() and/or content() static methods can be respectively called to produce a data change or an output.
152
-		 **/
153
-
154
-		// First we try explicit routes defined in App\Router
155
-		$router->collectRoutes();
156
-
157
-		$data = $router->getRouteCollector();
158
-		Core\Hook::callAll('route_collection', $data);
159
-
160
-		$module_class = $router->getModuleClass($args->getCommand());
161
-
162
-		// Then we try addon-provided modules that we wrap in the LegacyModule class
163
-		if (!$module_class && Core\Addon::isEnabled($this->module) && file_exists("addon/{$this->module}/{$this->module}.php")) {
164
-			//Check if module is an app and if public access to apps is allowed or not
165
-			$privateapps = $config->get('config', 'private_addons', false);
166
-			if ((!local_user()) && Core\Hook::isAddonApp($this->module) && $privateapps) {
167
-				$printNotAllowedAddon = true;
168
-			} else {
169
-				include_once "addon/{$this->module}/{$this->module}.php";
170
-				if (function_exists($this->module . '_module')) {
171
-					LegacyModule::setModuleFile("addon/{$this->module}/{$this->module}.php");
172
-					$module_class = LegacyModule::class;
173
-				}
174
-			}
175
-		}
176
-
177
-		/* Finally, we look for a 'standard' program module in the 'mod' directory
178
-		 * We emulate a Module class through the LegacyModule class
179
-		 */
180
-		if (!$module_class && file_exists("mod/{$this->module}.php")) {
181
-			LegacyModule::setModuleFile("mod/{$this->module}.php");
182
-			$module_class = LegacyModule::class;
183
-		}
184
-
185
-		$module_class = !isset($module_class) ? PageNotFound::class : $module_class;
186
-
187
-		return new Module($this->module, $module_class, $this->isBackend, $printNotAllowedAddon);
188
-	}
189
-
190
-	/**
191
-	 * Run the determined module class and calls all hooks applied to
192
-	 *
193
-	 * @param Core\L10n\L10n $l10n         The L10n instance
194
-	 * @param App            $app          The whole Friendica app (for method arguments)
195
-	 * @param LoggerInterface           $logger The Friendica logger
196
-	 * @param string         $currentTheme The chosen theme
197
-	 * @param array          $server       The $_SERVER variable
198
-	 * @param array          $post         The $_POST variables
199
-	 *
200
-	 * @throws \Friendica\Network\HTTPException\InternalServerErrorException
201
-	 */
202
-	public function run(Core\L10n\L10n $l10n, App $app,  LoggerInterface $logger, string $currentTheme, array $server, array $post)
203
-	{
204
-		if ($this->printNotAllowedAddon) {
205
-			info($l10n->t("You must be logged in to use addons. "));
206
-		}
207
-
208
-		/* The URL provided does not resolve to a valid module.
209
-		 *
210
-		 * On Dreamhost sites, quite often things go wrong for no apparent reason and they send us to '/internal_error.html'.
211
-		 * We don't like doing this, but as it occasionally accounts for 10-20% or more of all site traffic -
212
-		 * 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
213
-		 * this will often succeed and eventually do the right thing.
214
-		 *
215
-		 * Otherwise we are going to emit a 404 not found.
216
-		 */
217
-		if ($this->module_class === PageNotFound::class) {
218
-			$queryString = $server['QUERY_STRING'];
219
-			// Stupid browser tried to pre-fetch our Javascript img template. Don't log the event or return anything - just quietly exit.
220
-			if (!empty($queryString) && preg_match('/{[0-9]}/', $queryString) !== 0) {
221
-				exit();
222
-			}
223
-
224
-			if (!empty($queryString) && ($queryString === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
225
-				$logger->info('index.php: dreamhost_error_hack invoked.', ['Original URI' => $server['REQUEST_URI']]);
226
-				$app->internalRedirect($server['REQUEST_URI']);
227
-			}
228
-
229
-			$logger->debug('index.php: page not found.', ['request_uri' => $server['REQUEST_URI'], 'address' => $server['REMOTE_ADDR'], 'query' => $server['QUERY_STRING']]);
230
-		}
231
-
232
-		$placeholder = '';
233
-
234
-		Core\Hook::callAll($this->module . '_mod_init', $placeholder);
235
-
236
-		call_user_func([$this->module_class, 'init']);
237
-
238
-		// "rawContent" is especially meant for technical endpoints.
239
-		// This endpoint doesn't need any theme initialization or other comparable stuff.
240
-		call_user_func([$this->module_class, 'rawContent']);
241
-
242
-		// Load current theme info after module has been initialized as theme could have been set in module
243
-		$theme_info_file = 'view/theme/' . $currentTheme . '/theme.php';
244
-		if (file_exists($theme_info_file)) {
245
-			require_once $theme_info_file;
246
-		}
247
-
248
-		if (function_exists(str_replace('-', '_', $currentTheme) . '_init')) {
249
-			$func = str_replace('-', '_', $currentTheme) . '_init';
250
-			$func($app);
251
-		}
252
-
253
-		if ($server['REQUEST_METHOD'] === 'POST') {
254
-			Core\Hook::callAll($this->module . '_mod_post', $post);
255
-			call_user_func([$this->module_class, 'post']);
256
-		}
257
-
258
-		Core\Hook::callAll($this->module . '_mod_afterpost', $placeholder);
259
-		call_user_func([$this->module_class, 'afterpost']);
260
-	}
261
-
262
-	/**
263
-	 * @brief Checks if the site is called via a backend process
264
-	 *
265
-	 * This isn't a perfect solution. But we need this check very early.
266
-	 * So we cannot wait until the modules are loaded.
267
-	 *
268
-	 * @param string $module The determined module
269
-	 * @param array  $server The $_SERVER variable
270
-	 *
271
-	 * @return bool True, if the current module is called at backend
272
-	 */
273
-	private function checkBackend($module, array $server)
274
-	{
275
-		// Check if current module is in backend or backend flag is set
276
-		return basename(($server['PHP_SELF'] ?? ''), '.php') !== 'index' &&
277
-		       in_array($module, Module::BACKEND_MODULES);
278
-	}
279
-}

+ 3
- 1
src/Core/Installer.php View File

@@ -11,6 +11,7 @@ use Friendica\Database\Database;
11 11
 use Friendica\Database\DBStructure;
12 12
 use Friendica\Object\Image;
13 13
 use Friendica\Util\Network;
14
+use Friendica\Util\Profiler;
14 15
 use Friendica\Util\Strings;
15 16
 
16 17
 /**
@@ -590,7 +591,8 @@ class Installer
590 591
 	/**
591 592
 	 * Checking the Database connection and if it is available for the current installation
592 593
 	 *
593
-	 * @param Database $dba
594
+	 * @param ConfigCache $configCache The configuration cache
595
+	 * @param Profiler    $profiler    The profiler of this app
594 596
 	 *
595 597
 	 * @return bool true if the check was successful, otherwise false
596 598
 	 * @throws Exception

+ 23
- 0
src/Model/Profile.php View File

@@ -1224,6 +1224,29 @@ class Profile
1224 1224
 		return $uid;
1225 1225
 	}
1226 1226
 
1227
+	/**
1228
+	* Strip zrl parameter from a string.
1229
+	*
1230
+	* @param string $s The input string.
1231
+	* @return string The zrl.
1232
+	*/
1233
+	public static function stripZrls($s)
1234
+	{
1235
+		return preg_replace('/[\?&]zrl=(.*?)([\?&]|$)/is', '', $s);
1236
+	}
1237
+
1238
+	/**
1239
+	 * Strip query parameter from a string.
1240
+	 *
1241
+	 * @param string $s The input string.
1242
+	 * @param        $param
1243
+	 * @return string The query parameter.
1244
+	 */
1245
+	public static function stripQueryParam($s, $param)
1246
+	{
1247
+		return preg_replace('/[\?&]' . $param . '=(.*?)(&|$)/ism', '$2', $s);
1248
+	}
1249
+
1227 1250
 	/**
1228 1251
 	 * search for Profiles
1229 1252
 	 *

+ 2
- 2
src/Module/Install.php View File

@@ -111,7 +111,7 @@ class Install extends BaseModule
111 111
 				self::checkSetting($configCache, $_POST, 'database', 'database', '');
112 112
 
113 113
 				// If we cannot connect to the database, return to the previous step
114
-				if (!self::$installer->checkDB($a->getDBA())) {
114
+				if (!self::$installer->checkDB($configCache, $a->getProfiler())) {
115 115
 					self::$currentWizardStep = self::DATABASE_CONFIG;
116 116
 				}
117 117
 
@@ -135,7 +135,7 @@ class Install extends BaseModule
135 135
 				self::checkSetting($configCache, $_POST, 'config', 'admin_email', '');
136 136
 
137 137
 				// If we cannot connect to the database, return to the Database config wizard
138
-				if (!self::$installer->checkDB($a->getDBA())) {
138
+				if (!self::$installer->checkDB($configCache, $a->getProfiler())) {
139 139
 					self::$currentWizardStep = self::DATABASE_CONFIG;
140 140
 					return;
141 141
 				}

+ 20
- 32
static/dependencies.config.php View File

@@ -27,14 +27,14 @@ use Psr\Log\LoggerInterface;
27 27
  *
28 28
  */
29 29
 return [
30
-	'*'                             => [
30
+	'*' => [
31 31
 		// marks all class result as shared for other creations, so there's just
32 32
 		// one instance for the whole execution
33 33
 		'shared' => true,
34 34
 	],
35
-	'$basepath'                     => [
36
-		'instanceOf'      => Util\BasePath::class,
37
-		'call'            => [
35
+	'$basepath' => [
36
+		'instanceOf' => Util\BasePath::class,
37
+		'call' => [
38 38
 			['getPath', [], Dice::CHAIN_CALL],
39 39
 		],
40 40
 		'constructParams' => [
@@ -42,14 +42,14 @@ return [
42 42
 			$_SERVER
43 43
 		]
44 44
 	],
45
-	Util\BasePath::class            => [
45
+	Util\BasePath::class => [
46 46
 		'constructParams' => [
47 47
 			dirname(__FILE__, 2),
48 48
 			$_SERVER
49 49
 		]
50 50
 	],
51
-	Util\ConfigFileLoader::class    => [
52
-		'shared'          => true,
51
+	Util\ConfigFileLoader::class => [
52
+		'shared' => true,
53 53
 		'constructParams' => [
54 54
 			[Dice::INSTANCE => '$basepath'],
55 55
 		],
@@ -60,24 +60,24 @@ return [
60 60
 			['createCache', [], Dice::CHAIN_CALL],
61 61
 		],
62 62
 	],
63
-	App\Mode::class                 => [
64
-		'call' => [
63
+	App\Mode::class => [
64
+		'call'   => [
65 65
 			['determine', [], Dice::CHAIN_CALL],
66 66
 		],
67 67
 	],
68
-	Config\Configuration::class     => [
68
+	Config\Configuration::class => [
69 69
 		'instanceOf' => Factory\ConfigFactory::class,
70
-		'call'       => [
70
+		'call' => [
71 71
 			['createConfig', [], Dice::CHAIN_CALL],
72 72
 		],
73 73
 	],
74
-	Config\PConfiguration::class    => [
74
+	Config\PConfiguration::class => [
75 75
 		'instanceOf' => Factory\ConfigFactory::class,
76
-		'call'       => [
76
+		'call' => [
77 77
 			['createPConfig', [], Dice::CHAIN_CALL],
78 78
 		]
79 79
 	],
80
-	Database::class                 => [
80
+	Database::class => [
81 81
 		'constructParams' => [
82 82
 			[DICE::INSTANCE => \Psr\Log\NullLogger::class],
83 83
 			$_SERVER,
@@ -89,7 +89,7 @@ return [
89 89
 	 * Same as:
90 90
 	 *   $baseURL = new Util\BaseURL($configuration, $_SERVER);
91 91
 	 */
92
-	Util\BaseURL::class             => [
92
+	Util\BaseURL::class => [
93 93
 		'constructParams' => [
94 94
 			$_SERVER,
95 95
 		],
@@ -106,46 +106,34 @@ return [
106 106
 	 *    $app = $dice->create(App::class, [], ['$channel' => 'index']);
107 107
 	 *    and is automatically passed as an argument with the same name
108 108
 	 */
109
-	LoggerInterface::class          => [
109
+	LoggerInterface::class    => [
110 110
 		'instanceOf' => Factory\LoggerFactory::class,
111 111
 		'call'       => [
112 112
 			['create', [], Dice::CHAIN_CALL],
113 113
 		],
114 114
 	],
115
-	'$devLogger'                    => [
115
+	'$devLogger'              => [
116 116
 		'instanceOf' => Factory\LoggerFactory::class,
117 117
 		'call'       => [
118 118
 			['createDev', [], Dice::CHAIN_CALL],
119 119
 		]
120 120
 	],
121
-	Cache\ICache::class             => [
121
+	Cache\ICache::class       => [
122 122
 		'instanceOf' => Factory\CacheFactory::class,
123 123
 		'call'       => [
124 124
 			['create', [], Dice::CHAIN_CALL],
125 125
 		],
126 126
 	],
127
-	Cache\IMemoryCache::class       => [
127
+	Cache\IMemoryCache::class => [
128 128
 		'instanceOf' => Factory\CacheFactory::class,
129 129
 		'call'       => [
130 130
 			['create', [], Dice::CHAIN_CALL],
131 131
 		],
132 132
 	],
133
-	ILock::class                    => [
133
+	ILock::class              => [
134 134
 		'instanceOf' => Factory\LockFactory::class,
135 135
 		'call'       => [
136 136
 			['create', [], Dice::CHAIN_CALL],
137 137
 		],
138 138
 	],
139
-	App\Arguments::class => [
140
-		'instanceOf' => App\Arguments::class,
141
-		'call' => [
142
-			['determine', [$_SERVER, $_GET], Dice::CHAIN_CALL],
143
-		],
144
-	],
145
-	App\Module::class => [
146
-		'instanceOf' => App\Module::class,
147
-		'call' => [
148
-			['determineModule', [$_SERVER], Dice::CHAIN_CALL],
149
-		],
150
-	],
151 139
 ];

+ 0
- 242
tests/src/App/ArgumentsTest.php View File

@@ -1,242 +0,0 @@
1
-<?php
2
-
3
-namespace Friendica\Test\src\App;
4
-
5
-use Friendica\App;
6
-use PHPUnit\Framework\TestCase;
7
-
8
-class ArgumentsTest extends TestCase
9
-{
10
-	private function assertArguments(array $assert, App\Arguments $arguments)
11
-	{
12
-		$this->assertEquals($assert['queryString'], $arguments->getQueryString());
13
-		$this->assertEquals($assert['command'], $arguments->getCommand());
14
-		$this->assertEquals($assert['argv'], $arguments->getArgv());
15
-		$this->assertEquals($assert['argc'], $arguments->getArgc());
16
-		$this->assertCount($assert['argc'], $arguments->getArgv());
17
-	}
18
-
19
-	/**
20
-	 * Test the default argument without any determinations
21
-	 */
22
-	public function testDefault()
23
-	{
24
-		$arguments = new App\Arguments();
25
-
26
-		$this->assertArguments([
27
-			'queryString' => '',
28
-			'command'     => '',
29
-			'argv'        => ['home'],
30
-			'argc'        => 1,
31
-		],
32
-			$arguments);
33
-	}
34
-
35
-	public function dataArguments()
36
-	{
37
-		return [
38
-			'withPagename'         => [
39
-				'assert' => [
40
-					'queryString' => 'profile/test/it?arg1=value1&arg2=value2',
41
-					'command'     => 'profile/test/it',
42
-					'argv'        => ['profile', 'test', 'it'],
43
-					'argc'        => 3,
44
-				],
45
-				'server' => [
46
-					'QUERY_STRING' => 'pagename=profile/test/it?arg1=value1&arg2=value2',
47
-				],
48
-				'get'    => [
49
-					'pagename' => 'profile/test/it',
50
-				],
51
-			],
52
-			'withQ'                => [
53
-				'assert' => [
54
-					'queryString' => 'profile/test/it?arg1=value1&arg2=value2',
55
-					'command'     => 'profile/test/it',
56
-					'argv'        => ['profile', 'test', 'it'],
57
-					'argc'        => 3,
58
-				],
59
-				'server' => [
60
-					'QUERY_STRING' => 'q=profile/test/it?arg1=value1&arg2=value2',
61
-				],
62
-				'get'    => [
63
-					'q' => 'profile/test/it',
64
-				],
65
-			],
66
-			'withWrongDelimiter'   => [
67
-				'assert' => [
68
-					'queryString' => 'profile/test/it?arg1=value1&arg2=value2',
69
-					'command'     => 'profile/test/it',
70
-					'argv'        => ['profile', 'test', 'it'],
71
-					'argc'        => 3,
72
-				],
73
-				'server' => [
74
-					'QUERY_STRING' => 'pagename=profile/test/it&arg1=value1&arg2=value2',
75
-				],
76
-				'get'    => [
77
-					'pagename' => 'profile/test/it',
78
-				],
79
-			],
80
-			'withUnixHomeDir'      => [
81
-				'assert' => [
82
-					'queryString' => '~test/it?arg1=value1&arg2=value2',
83
-					'command'     => 'profile/test/it',
84
-					'argv'        => ['profile', 'test', 'it'],
85
-					'argc'        => 3,
86
-				],
87
-				'server' => [
88
-					'QUERY_STRING' => 'pagename=~test/it?arg1=value1&arg2=value2',
89
-				],
90
-				'get'    => [
91
-					'pagename' => '~test/it',
92
-				],
93
-			],
94
-			'withDiasporaHomeDir'  => [
95
-				'assert' => [
96
-					'queryString' => 'u/test/it?arg1=value1&arg2=value2',
97
-					'command'     => 'profile/test/it',
98
-					'argv'        => ['profile', 'test', 'it'],
99
-					'argc'        => 3,
100
-				],
101
-				'server' => [
102
-					'QUERY_STRING' => 'pagename=u/test/it?arg1=value1&arg2=value2',
103
-				],
104
-				'get'    => [
105
-					'pagename' => 'u/test/it',
106
-				],
107
-			],
108
-			'withTrailingSlash'    => [
109
-				'assert' => [
110
-					'queryString' => 'profile/test/it?arg1=value1&arg2=value2/',
111
-					'command'     => 'profile/test/it',
112
-					'argv'        => ['profile', 'test', 'it'],
113
-					'argc'        => 3,
114
-				],
115
-				'server' => [
116
-					'QUERY_STRING' => 'pagename=profile/test/it?arg1=value1&arg2=value2/',
117
-				],
118
-				'get'    => [
119
-					'pagename' => 'profile/test/it',
120
-				],
121
-			],
122
-			'withWrongQueryString' => [
123
-				'assert' => [
124
-					// empty query string?!
125
-					'queryString' => '',
126
-					'command'     => 'profile/test/it',
127
-					'argv'        => ['profile', 'test', 'it'],
128
-					'argc'        => 3,
129
-				],
130
-				'server' => [
131
-					'QUERY_STRING' => 'wrong=profile/test/it?arg1=value1&arg2=value2/',
132
-				],
133
-				'get'    => [
134
-					'pagename' => 'profile/test/it',
135
-				],
136
-			],
137
-			'withMissingPageName'  => [
138
-				'assert' => [
139
-					'queryString' => 'notvalid/it?arg1=value1&arg2=value2/',
140
-					'command'     => App\Module::DEFAULT,
141
-					'argv'        => [App\Module::DEFAULT],
142
-					'argc'        => 1,
143
-				],
144
-				'server' => [
145
-					'QUERY_STRING' => 'pagename=notvalid/it?arg1=value1&arg2=value2/',
146
-				],
147
-				'get'    => [
148
-				],
149
-			],
150
-		];
151
-	}
152
-
153
-	/**
154
-	 * Test all variants of argument determination
155
-	 *
156
-	 * @dataProvider dataArguments
157
-	 */
158
-	public function testDetermine(array $assert, array $server, array $get)
159
-	{
160
-		$arguments = (new App\Arguments())
161
-			->determine($server, $get);
162
-
163
-		$this->assertArguments($assert, $arguments);
164
-	}
165
-
166
-	/**
167
-	 * Test if the get/has methods are working for the determined arguments
168
-	 *
169
-	 * @dataProvider dataArguments
170
-	 */
171
-	public function testGetHas(array $assert, array $server, array $get)
172
-	{
173
-		$arguments = (new App\Arguments())
174
-			->determine($server, $get);
175
-
176
-		for ($i = 0; $i < $arguments->getArgc(); $i++) {
177
-			$this->assertTrue($arguments->has($i));
178
-			$this->assertEquals($assert['argv'][$i], $arguments->get($i));
179
-		}
180
-
181
-		$this->assertFalse($arguments->has($arguments->getArgc()));
182
-		$this->assertEmpty($arguments->get($arguments->getArgc()));
183
-		$this->assertEquals('default', $arguments->get($arguments->getArgc(), 'default'));
184
-	}
185
-
186
-	public function dataStripped()
187
-	{
188
-		return [
189
-			'strippedZRLFirst'  => [
190
-				'assert' => '?arg1=value1',
191
-				'input'  => '?zrl=nope&arg1=value1',
192
-			],
193
-			'strippedZRLLast'   => [
194
-				'assert' => '?arg1=value1',
195
-				'input'  => '?arg1=value1&zrl=nope',
196
-			],
197
-			'strippedZTLMiddle' => [
198
-				'assert' => '?arg1=value1&arg2=value2',
199
-				'input'  => '?arg1=value1&zrl=nope&arg2=value2',
200
-			],
201
-			'strippedOWTFirst'  => [
202
-				'assert' => '?arg1=value1',
203
-				'input'  => '?owt=test&arg1=value1',
204
-			],
205
-			'strippedOWTLast'   => [
206
-				'assert' => '?arg1=value1',
207
-				'input'  => '?arg1=value1&owt=test',
208
-			],
209
-			'strippedOWTMiddle' => [
210
-				'assert' => '?arg1=value1&arg2=value2',
211
-				'input'  => '?arg1=value1&owt=test&arg2=value2',
212
-			],
213
-		];
214
-	}
215
-
216
-	/**
217
-	 * Test the ZRL and OWT stripping
218
-	 *
219
-	 * @dataProvider dataStripped
220
-	 */
221
-	public function testStrippedQueries(string $assert, string $input)
222
-	{
223
-		$command = 'test/it';
224
-
225
-		$arguments = (new App\Arguments())
226
-			->determine(['QUERY_STRING' => 'q=' . $command . $input,], ['pagename' => $command]);
227
-
228
-		$this->assertEquals($command . $assert, $arguments->getQueryString());
229
-	}
230
-
231
-	/**
232
-	 * Test that arguments are immutable
233
-	 */
234
-	public function testImmutable()
235
-	{
236
-		$argument = new App\Arguments();
237
-
238
-		$argNew = $argument->determine([], []);
239
-
240
-		$this->assertNotSame($argument, $argNew);
241
-	}
242
-}

+ 15
- 32
tests/src/App/ModeTest.php View File

@@ -38,20 +38,22 @@ class ModeTest extends MockedTest
38 38
 		$this->setUpVfsDir();
39 39
 
40 40
 		$this->basePathMock = \Mockery::mock(BasePath::class);
41
+		$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
42
+
41 43
 		$this->databaseMock = \Mockery::mock(Database::class);
42 44
 		$this->configCacheMock = \Mockery::mock(Config\Cache\ConfigCache::class);
43 45
 	}
44 46
 
45 47
 	public function testItEmpty()
46 48
 	{
47
-		$mode = new Mode();
49
+		$mode = new Mode($this->basePathMock, $this->databaseMock, $this->configCacheMock);
48 50
 		$this->assertTrue($mode->isInstall());
49 51
 		$this->assertFalse($mode->isNormal());
50 52
 	}
51 53
 
52 54
 	public function testWithoutConfig()
53 55
 	{
54
-		$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
56
+		$mode = new Mode($this->basePathMock, $this->databaseMock, $this->configCacheMock);
55 57
 
56 58
 		$this->assertTrue($this->root->hasChild('config/local.config.php'));
57 59
 
@@ -59,7 +61,7 @@ class ModeTest extends MockedTest
59 61
 
60 62
 		$this->assertFalse($this->root->hasChild('config/local.config.php'));
61 63
 
62
-		$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
64
+		$mode->determine();
63 65
 
64 66
 		$this->assertTrue($mode->isInstall());
65 67
 		$this->assertFalse($mode->isNormal());
@@ -69,11 +71,10 @@ class ModeTest extends MockedTest
69 71
 
70 72
 	public function testWithoutDatabase()
71 73
 	{
72
-		$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
73
-
74 74
 		$this->databaseMock->shouldReceive('connected')->andReturn(false)->once();
75 75
 
76
-		$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
76
+		$mode = new Mode($this->basePathMock, $this->databaseMock, $this->configCacheMock);
77
+		$mode->determine();
77 78
 
78 79
 		$this->assertFalse($mode->isNormal());
79 80
 		$this->assertTrue($mode->isInstall());
@@ -84,13 +85,12 @@ class ModeTest extends MockedTest
84 85
 
85 86
 	public function testWithoutDatabaseSetup()
86 87
 	{
87
-		$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
88
-
89 88
 		$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
90 89
 		$this->databaseMock->shouldReceive('fetchFirst')
91 90
 		                   ->with('SHOW TABLES LIKE \'config\'')->andReturn(false)->once();
92 91
 
93
-		$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
92
+		$mode = new Mode($this->basePathMock, $this->databaseMock, $this->configCacheMock);
93
+		$mode->determine();
94 94
 
95 95
 		$this->assertFalse($mode->isNormal());
96 96
 		$this->assertTrue($mode->isInstall());
@@ -100,15 +100,14 @@ class ModeTest extends MockedTest
100 100
 
101 101
 	public function testWithMaintenanceMode()
102 102
 	{
103
-		$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
104
-
105 103
 		$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
106 104
 		$this->databaseMock->shouldReceive('fetchFirst')
107 105
 		                   ->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
108 106
 		$this->configCacheMock->shouldReceive('get')->with('system', 'maintenance')
109 107
 		                      ->andReturn(true)->once();
110 108
 
111
-		$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
109
+		$mode = new Mode($this->basePathMock, $this->databaseMock, $this->configCacheMock);
110
+		$mode->determine();
112 111
 
113 112
 		$this->assertFalse($mode->isNormal());
114 113
 		$this->assertFalse($mode->isInstall());
@@ -119,8 +118,6 @@ class ModeTest extends MockedTest
119 118
 
120 119
 	public function testNormalMode()
121 120
 	{
122
-		$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
123
-
124 121
 		$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
125 122
 		$this->databaseMock->shouldReceive('fetchFirst')
126 123
 		                   ->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
@@ -130,7 +127,8 @@ class ModeTest extends MockedTest
130 127
 		                   ->with('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])
131 128
 		                   ->andReturn(['v' => null])->once();
132 129
 
133
-		$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
130
+		$mode = new Mode($this->basePathMock, $this->databaseMock, $this->configCacheMock);
131
+		$mode->determine();
134 132
 
135 133
 		$this->assertTrue($mode->isNormal());
136 134
 		$this->assertFalse($mode->isInstall());
@@ -144,8 +142,6 @@ class ModeTest extends MockedTest
144 142
 	 */
145 143
 	public function testDisabledMaintenance()
146 144
 	{
147
-		$this->basePathMock->shouldReceive('getPath')->andReturn($this->root->url())->once();
148
-
149 145
 		$this->databaseMock->shouldReceive('connected')->andReturn(true)->once();
150 146
 		$this->databaseMock->shouldReceive('fetchFirst')
151 147
 		                   ->with('SHOW TABLES LIKE \'config\'')->andReturn(true)->once();
@@ -155,7 +151,8 @@ class ModeTest extends MockedTest
155 151
 		                   ->with('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])
156 152
 		                   ->andReturn(['v' => '0'])->once();
157 153
 
158
-		$mode = (new Mode())->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
154
+		$mode = new Mode($this->basePathMock, $this->databaseMock, $this->configCacheMock);
155
+		$mode->determine();
159 156
 
160 157
 		$this->assertTrue($mode->isNormal());
161 158
 		$this->assertFalse($mode->isInstall());
@@ -163,18 +160,4 @@ class ModeTest extends MockedTest
163 160
 		$this->assertTrue($mode->has(Mode::DBCONFIGAVAILABLE));
164 161
 		$this->assertTrue($mode->has(Mode::MAINTENANCEDISABLED));
165 162
 	}
166
-
167
-	/**
168
-	 * Test that modes are immutable
169
-	 */
170
-	public function testImmutable()
171
-	{
172
-		$this->basePathMock->shouldReceive('getPath')->andReturn(null)->once();
173
-
174
-		$mode = new Mode();
175
-
176
-		$modeNew = $mode->determine($this->basePathMock, $this->databaseMock, $this->configCacheMock);
177
-
178
-		$this->assertNotSame($modeNew, $mode);
179
-	}
180 163
 }

+ 0
- 189
tests/src/App/ModuleTest.php View File

@@ -1,189 +0,0 @@
1
-<?php
2
-
3
-namespace Friendica\Test\src\App;
4
-
5
-use Friendica\App;
6
-use Friendica\Core\Config\Configuration;
7
-use Friendica\LegacyModule;
8
-use Friendica\Module\PageNotFound;
9
-use Friendica\Module\WellKnown\HostMeta;
10
-use Friendica\Test\DatabaseTest;
11
-
12
-class ModuleTest extends DatabaseTest
13
-{
14
-	private function assertModule(array $assert, App\Module $module)
15
-	{
16
-		$this->assertEquals($assert['isBackend'], $module->isBackend());
17
-		$this->assertEquals($assert['name'], $module->getName());
18
-		$this->assertEquals($assert['class'], $module->getClassName());
19
-	}
20
-
21
-	/**
22
-	 * Test the default module mode
23
-	 */
24
-	public function testDefault()
25
-	{
26
-		$module = new App\Module();
27
-
28
-		$this->assertModule([
29
-			'isBackend' => false,
30
-			'name'      => App\Module::DEFAULT,
31
-			'class'     => App\Module::DEFAULT_CLASS,
32
-		], $module);
33
-	}
34
-
35
-	public function dataModuleName()
36
-	{
37
-		return [
38
-			'default'                   => [
39
-				'assert' => [
40
-					'isBackend' => false,
41
-					'name'      => 'network',
42
-					'class'     => App\Module::DEFAULT_CLASS,
43
-				],
44
-				'args'   => new App\Arguments('network/data/in',
45
-					'network/data/in',
46
-					['network', 'data', 'in'],
47
-					3),
48
-				'server' => [],
49
-			],
50
-			'withStrikeAndPoint'        => [
51
-				'assert' => [
52
-					'isBackend' => false,
53
-					'name'      => 'with_strike_and_point',
54
-					'class'     => App\Module::DEFAULT_CLASS,
55
-				],
56
-				'args'   => new App\Arguments('with-strike.and-point/data/in',
57
-					'with-strike.and-point/data/in',
58
-					['with-strike.and-point', 'data', 'in'],
59
-					3),
60
-				'server' => [],
61
-			],
62
-			'withNothing'               => [
63
-				'assert' => [
64
-					'isBackend' => false,
65
-					'name'      => App\Module::DEFAULT,
66
-					'class'     => App\Module::DEFAULT_CLASS,
67
-				],
68
-				'args'   => new App\Arguments(),
69
-				'server' => []
70
-			],
71
-			'withIndex'                 => [
72
-				'assert' => [
73
-					'isBackend' => false,
74
-					'name'      => App\Module::DEFAULT,
75
-					'class'     => App\Module::DEFAULT_CLASS,
76
-				],
77
-				'args'   => new App\Arguments(),
78
-				'server' => ['PHP_SELF' => 'index.php']
79
-			],
80
-			'withIndexButBackendMod'    => [
81
-				'assert' => [
82
-					'isBackend' => false,
83
-					'name'      => App\Module::BACKEND_MODULES[0],
84
-					'class'     => App\Module::DEFAULT_CLASS,
85
-				],
86
-				'args'   => new App\Arguments(App\Module::BACKEND_MODULES[0] . '/data/in',
87
-					App\Module::BACKEND_MODULES[0] . '/data/in',
88
-					[App\Module::BACKEND_MODULES[0], 'data', 'in'],
89
-					3),
90
-				'server' => ['PHP_SELF' => 'index.php']
91
-			],
92
-			'withNotIndexAndBackendMod' => [
93
-				'assert' => [
94
-					'isBackend' => true,
95
-					'name'      => App\Module::BACKEND_MODULES[0],
96
-					'class'     => App\Module::DEFAULT_CLASS,
97
-				],
98
-				'args'   => new App\Arguments(App\Module::BACKEND_MODULES[0] . '/data/in',
99
-					App\Module::BACKEND_MODULES[0] . '/data/in',
100
-					[App\Module::BACKEND_MODULES[0], 'data', 'in'],
101
-					3),
102
-				'server' => ['PHP_SELF' => 'daemon.php']
103
-			],
104
-			'withFirefoxApp'            => [
105
-				'assert' => [
106
-					'isBackend' => false,
107
-					'name'      => 'login',
108
-					'class'     => App\Module::DEFAULT_CLASS,
109
-				],
110
-				'args'   => new App\Arguments('users/sign_in',
111
-					'users/sign_in',
112
-					['users', 'sign_in'],
113
-					3),
114
-				'server' => ['PHP_SELF' => 'index.php'],
115
-			],
116
-		];
117
-	}
118
-
119
-	/**
120
-	 * Test the module name and backend determination
121
-	 *
122
-	 * @dataProvider dataModuleName
123
-	 */
124
-	public function testModuleName(array $assert, App\Arguments $args, array $server)
125
-	{
126
-		$module = (new App\Module())->determineModule($args, $server);
127
-
128
-		$this->assertModule($assert, $module);
129
-	}
130
-
131
-	public function dataModuleClass()
132
-	{
133
-		return [
134
-			'default' => [
135
-				'assert'  => App\Module::DEFAULT_CLASS,
136
-				'name'    => App\Module::DEFAULT,
137
-				'command' => App\Module::DEFAULT,
138
-				'privAdd' => false,
139
-			],
140
-			'legacy'  => [
141
-				'assert'  => LegacyModule::class,
142
-				// API is one of the last modules to switch from legacy to new BaseModule
143
-				// so this should be a stable test case until we completely switch ;-)
144
-				'name'    => 'api',
145
-				'command' => 'api/test/it',
146
-				'privAdd' => false,
147
-			],
148
-			'new'     => [
149
-				'assert'  => HostMeta::class,
150
-				'not_required',
151
-				'command' => '.well-known/host-meta',
152
-				'privAdd' => false,
153
-			],
154
-			'404'     => [
155
-				'assert'  => PageNotFound::class,
156
-				'name'    => 'invalid',
157
-				'command' => 'invalid',
158
-				'privAdd' => false,
159
-			]
160
-		];
161
-	}
162
-
163
-	/**
164
-	 * Test the determination of the module class
165
-	 *
166
-	 * @dataProvider dataModuleClass
167
-	 */
168
-	public function testModuleClass($assert, string $name, string $command, bool $privAdd)
169
-	{
170
-		$config = \Mockery::mock(Configuration::class);
171
-		$config->shouldReceive('get')->with('config', 'private_addons', false)->andReturn($privAdd)->atMost()->once();
172
-
173
-		$module = (new App\Module($name))->determineClass(new App\Arguments('', $command), new App\Router(), $config);
174
-
175
-		$this->assertEquals($assert, $module->getClassName());
176
-	}
177
-
178
-	/**
179
-	 * Test that modules are immutable
180
-	 */
181
-	public function testImmutable()
182
-	{
183
-		$module = new App\Module();
184
-
185
-		$moduleNew = $module->determineModule(new App\Arguments(), []);
186
-
187
-		$this->assertNotSame($moduleNew, $module);
188
-	}
189
-}

Loading…
Cancel
Save