From c7a6a539a9c3fe2455dbaae85841033b797626a4 Mon Sep 17 00:00:00 2001 From: slawkens Date: Thu, 13 Jun 2024 21:35:47 +0200 Subject: [PATCH] Another approach to fix duplicates - priorities Priority description: (lower number - higher priority) 1-99 Highest priority - overrides everything, even pages from database, use with caption 100 - default for pages in database 101-999 - recommended range for plugins 1000 - default value for plugins if no other specified 1001 - 9999 - no usage currently 10000 - default myaac routes --- plugins/example.json | 2 ++ system/router.php | 64 +++++++++++++++++++++++++++++++----------- system/routes.php | 6 ++-- system/src/Plugins.php | 42 ++++++++++----------------- 4 files changed, 68 insertions(+), 46 deletions(-) diff --git a/plugins/example.json b/plugins/example.json index 0abfb3bf..24c608c9 100644 --- a/plugins/example.json +++ b/plugins/example.json @@ -40,6 +40,8 @@ "redirect_to": "account/manage" } }, + "routes-default-priority": 1000, + "pages-default-priority": 1000, "settings": "plugins/your-plugin-folder/settings.php", "autoload": { "pages": true, diff --git a/system/router.php b/system/router.php index b6ecca7a..0a5ed7f8 100644 --- a/system/router.php +++ b/system/router.php @@ -91,34 +91,66 @@ if($logged && $account_logged && $account_logged->isLoaded()) { $dispatcher = FastRoute\cachedDispatcher(function (FastRoute\RouteCollector $r) { $routes = require SYSTEM . 'routes.php'; - $isAlreadyDefined = []; - $routesFinal = []; foreach(getDatabasePages() as $page) { - $isAlreadyDefined[$page] = true; - $routesFinal[] = ['*', $page, '__database__/' . $page, true]; + $routesFinal[] = ['*', $page, '__database__/' . $page, 100]; } Plugins::clearWarnings(); foreach (Plugins::getRoutes() as $route) { - if(!isset($isAlreadyDefined[$route[1]])) { - $isAlreadyDefined[$route[1]] = true; - $routesFinal[] = [$route[0], $route[1], $route[2]]; - } + $routesFinal[] = [$route[0], $route[1], $route[2], $route[3] ?? 1000]; +/* + echo '
';
+		var_dump($route[1], $route[3], $route[2]);
+		echo '/
';
+*/
 	}
 
 	foreach ($routes as $route) {
-		if(!isset($isAlreadyDefined[$route[1]])) {
-			if (strpos($route[2], '__redirect__') === false && strpos($route[2], '__database__') === false) {
-				$routesFinal[] = [$route[0], $route[1], 'system/pages/' . $route[2]];
-			}
-			else {
-				$routesFinal[] = [$route[0], $route[1], $route[2]];
-			}
-			$isAlreadyDefined[$route[1]] = true;
+		if (!str_contains($route[2], '__redirect__') && !str_contains($route[2], '__database__')) {
+			$routesFinal[] = [$route[0], $route[1], 'system/pages/' . $route[2], $route[3] ?? 10000];
+		}
+		else {
+			$routesFinal[] = [$route[0], $route[1], $route[2], $route[3] ?? 10000];
 		}
 	}
 
+	// sort required for the next step (filter)
+	usort($routesFinal, function ($a, $b)
+	{
+		// key 3 is priority
+		if ($a[3] == $b[3]) {
+			return 0;
+		}
+
+		return ($a[3] < $b[3]) ? -1 : 1;
+	});
+
+	// remove duplicates
+	// if same route pattern, but different priority
+	$routesFinal = array_filter($routesFinal, function ($a) {
+		$aliases = [
+			[':int', ':string', ':alphanum'],
+			[':\d+', ':[A-Za-z0-9-_%+\' ]+', ':[A-Za-z0-9]+'],
+		];
+
+		// apply aliases
+		$a[1] = str_replace($aliases[0], $aliases[1], $a[1]);
+
+		static $duplicates = [];
+		if (isset($duplicates[$a[1]])) {
+			return false;
+		}
+
+		$duplicates[$a[1]] = true;
+		return true;
+	});
+/*
+	echo '
';
+	var_dump($routesFinal);
+	echo '
'; + die; +*/ foreach ($routesFinal as $route) { if ($route[0] === '*') { $route[0] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']; diff --git a/system/routes.php b/system/routes.php index 86fcdd30..576c14b2 100644 --- a/system/routes.php +++ b/system/routes.php @@ -15,9 +15,9 @@ return [ ['GET', 'news/{id:int}', 'news/archive.php'], // block access to some files - ['*', 'account/base', '404.php'], // this is to block account/base.php - ['*', 'forum/base', '404.php'], - ['*', 'guilds/base', '404.php'], + ['*', 'account/base', '404.php', 10], // this is to block account/base.php + ['*', 'forum/base', '404.php', 10], + ['*', 'guilds/base', '404.php', 10], [['GET', 'POST'], 'account/password', 'account/change_password.php'], [['GET', 'POST'], 'account/register/new', 'account/register_new.php'], diff --git a/system/src/Plugins.php b/system/src/Plugins.php index 6cb3ee0a..08f7be50 100644 --- a/system/src/Plugins.php +++ b/system/src/Plugins.php @@ -24,9 +24,9 @@ class Plugins { $duplicates = []; $routes = []; foreach(self::getAllPluginsJson() as $plugin) { - $priority = 100; - if (isset($plugin['priority'])) { - $priority = $plugin['priority']; + $routesDefaultPriority = 1000; + if (isset($plugin['routes-default-priority'])) { + $routesDefaultPriority = $plugin['routes-default-priority']; } $warningPreTitle = 'Plugin: ' . $plugin['name'] . ' - '; @@ -49,7 +49,7 @@ class Plugins { } if (!isset($info['priority'])) { - $info['priority'] = 100; // default priority + $info['priority'] = $routesDefaultPriority; // default priority taken from plugin.json } if (isset($info['redirect_from'])) { @@ -68,27 +68,15 @@ class Plugins { // replace first occurrence of / in pattern if found (will be auto-added later) removeIfFirstSlash($info['pattern']); - foreach ($routes as $id => &$route) { - if($route[1] == $info['pattern']) { - if($info['priority'] < $route[3]) { - self::$warnings[] = $warningPreTitle . "Duplicated route with lower priority: {$info['pattern']}. Disabling this route..."; - continue 2; - } - else { - self::$warnings[] = $warningPreTitle . "Duplicated route with lower priority: {$route[1]} ({$route[3]}). Disabling this route..."; - unset($routes[$id]); - } - } - } - - $tmp = preg_replace("/\[[^)]+\]/",'', $info['pattern']); - if (!isset($duplicates[$tmp])) { - $routes[] = [$methods, $info['pattern'], $info['file'], $info['priority']]; - $duplicates[$tmp] = true; - } + $routes[] = [$methods, $info['pattern'], $info['file'], $info['priority']]; } } + $pagesDefaultPriority = 1000; + if (isset($plugin['pages-default-priority'])) { + $pagesDefaultPriority = $plugin['pages-default-priority']; + } + if (self::getAutoLoadOption($plugin, 'pages', true)) { // // Get all plugins/*/pages/*.php pages @@ -99,7 +87,7 @@ class Plugins { $name = pathinfo($file, PATHINFO_FILENAME); if (!isset($duplicates[$name])) { - $routes[] = [['get', 'post'], $name, $file, $priority]; + $routes[] = [['get', 'post'], $name, $file, $pagesDefaultPriority]; $duplicates[$name] = true; } } @@ -119,7 +107,7 @@ class Plugins { $name = $folderName . '/' . pathinfo($file, PATHINFO_FILENAME); if (!isset($duplicates[$name])) { - $routes[] = [['get', 'post'], $name, $file, $priority]; + $routes[] = [['get', 'post'], $name, $file, $pagesDefaultPriority]; $duplicates[$name] = true; } } @@ -139,9 +127,9 @@ class Plugins { // cleanup before passing back // priority is not needed anymore - foreach ($routes as &$route) { - unset($route[3]); - } + //foreach ($routes as &$route) { + // unset($route[3]); + //} if ($cache->enabled()) { $cache->set('plugins_routes', serialize($routes), 600);