From 4f37a9e447c9d03f3685d78148d482d8d43c3997 Mon Sep 17 00:00:00 2001 From: Molkobain Date: Tue, 13 Dec 2022 11:42:00 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B05655=20-=20Router:=20Add=20method=20to?= =?UTF-8?q?=20dump=20available=20routes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/UI.php | 1 - sources/Router/Router.php | 44 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/pages/UI.php b/pages/UI.php index b9f043fda..907a11706 100644 --- a/pages/UI.php +++ b/pages/UI.php @@ -327,7 +327,6 @@ try // Response is a \WebPage, let's handle it like legacy operations $oP = $mResponse; - // TODO 3.1: If no route match, die instead of fallback to legacy operation dispatch and dump available routes if in dev env. } // Otherwise, use legacy operation else { diff --git a/sources/Router/Router.php b/sources/Router/Router.php index 7493ae915..4607b4f76 100644 --- a/sources/Router/Router.php +++ b/sources/Router/Router.php @@ -6,6 +6,8 @@ namespace Combodo\iTop\Router; +use ReflectionClass; +use ReflectionMethod; use utils; /** @@ -35,6 +37,44 @@ class Router return static::$oSingleton; } + /** + * @return array{0: string, 1: string} Array of available routes namespaces and their corresponding controllers (eg. ['object' => '\Combodo\iTop\Controller\Base\Layout\ObjectController', ...]) + */ + public static function GetRoutesNamespaces(): array + { + $aRoutesNamespaces = []; + foreach (utils::GetClassesForInterface('Combodo\iTop\Controller\iController', '', ['[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]']) as $sControllerFQCN) { + $aRoutesNamespaces[$sControllerFQCN::ROUTE_NAMESPACE] = $sControllerFQCN; + } + + return $aRoutesNamespaces; + } + + /** + * @return array{0: string, 1: string} Array of available routes and their corresponding controllers (eg. ['object.modify' => '\Combodo\iTop\Controller\Base\Layout\ObjectController::OperationModify', ...]) + * @throws \ReflectionException + */ + public static function GetRoutes(): array + { + $aRoutes = []; + foreach (static::GetRoutesNamespaces() as $sRouteNamespace => $sRouteControllerFQCN) { + $oReflectionClass = new ReflectionClass($sRouteControllerFQCN); + foreach ($oReflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $oReflectionMethod) { + // Ignore non "operation" methods + $sPrefix = 'Operation'; + $iPos = stripos($oReflectionMethod->name, $sPrefix); + if ($iPos !== 0) { + continue; + } + + $sOperationName = substr($oReflectionMethod->name, $iPos + strlen($sPrefix)); + $aRoutes[$sRouteNamespace.'.'.utils::ToSnakeCase($sOperationName)] = $sRouteControllerFQCN.'::'.$oReflectionMethod->name; + } + } + + return $aRoutes; + } + /**********************/ /* Non-static methods */ /**********************/ @@ -161,8 +201,8 @@ class Router */ protected function FindControllerFromRouteNamespace(string $sRouteNamespace): ?string { - foreach (utils::GetClassesForInterface('Combodo\iTop\Controller\iController', '', ['[\\\\/]lib[\\\\/]', '[\\\\/]node_modules[\\\\/]', '[\\\\/]test[\\\\/]']) as $sControllerFQCN) { - if ($sControllerFQCN::ROUTE_NAMESPACE === $sRouteNamespace) { + foreach (static::GetRoutesNamespaces() as $sControllerRouteNamespace => $sControllerFQCN) { + if ($sControllerRouteNamespace === $sRouteNamespace) { return $sControllerFQCN; } }