From f98e7cf219af7fcb4c9070f05c716f453c888607 Mon Sep 17 00:00:00 2001 From: Alexander Ebert Date: Wed, 12 Oct 2011 13:46:34 +0200 Subject: [PATCH] LinkHandler now supports routing --- .../lib/system/request/LinkHandler.class.php | 53 +++++++++++++----- .../files/lib/system/request/Route.class.php | 55 +++++++++++++++++++ .../lib/system/request/RouteHandler.class.php | 31 ++++++++++- .../plugin/LinkBlockTemplatePlugin.class.php | 7 +-- 4 files changed, 126 insertions(+), 20 deletions(-) diff --git a/wcfsetup/install/files/lib/system/request/LinkHandler.class.php b/wcfsetup/install/files/lib/system/request/LinkHandler.class.php index 02b927c388..09ccf76bd6 100644 --- a/wcfsetup/install/files/lib/system/request/LinkHandler.class.php +++ b/wcfsetup/install/files/lib/system/request/LinkHandler.class.php @@ -1,6 +1,7 @@ getActiveGroup(); - - // not within an application group, return unmodified url - if ($applicationGroup === null) { - return $url . (strstr($url, '?') === false ? SID_ARG_1ST : SID_ARG_2ND_NOT_ENCODED); + public function getLink($url, array $parameters = array()) { + $abbreviation = 'wcf'; + $isRaw = false; + if (isset($parameters['application'])) { + $abbreviation = $parameters['application']; + unset($parameters['application']); + } + if (isset($parameters['isRaw'])) { + $isRaw = $parameters['isRaw']; + unset($parameters['isRaw']); } - // try to resolve abbreviation - $application = null; - if ($abbreviation != 'wcf') { - $application = ApplicationHandler::getInstance()->getApplication($abbreviation); + // build route + if (isset($parameters['controller'])) { + $routeURL = RouteHandler::getInstance()->buildRoute($parameters); + if (!$isRaw) { + $routeURL .= (strpos($routeURL, '?') === false) ? '?' : '&'; + } + $url = $routeURL . $url; } - // fallback to primary application if abbreviation is 'wcf' or unknown - if ($application === null) { - $application = ApplicationHandler::getInstance()->getPrimaryApplication(); + // append session id + $url .= (strpos($url, '?') === false) ? SID_ARG_1ST : SID_ARG_2ND_NOT_ENCODED; + + // handle application groups + $applicationGroup = ApplicationHandler::getInstance()->getActiveGroup(); + if ($applicationGroup !== null) { + // try to resolve abbreviation + $application = null; + if ($abbreviation != 'wcf') { + $application = ApplicationHandler::getInstance()->getApplication($abbreviation); + } + + // fallback to primary application if abbreviation is 'wcf' or unknown + if ($application === null) { + $application = ApplicationHandler::getInstance()->getPrimaryApplication(); + } + + $url = $application->domainName . $application->domainPath . $url; } - return $application->domainName . $application->domainPath . $url . (strstr($url, '?') === false ? SID_ARG_1ST : SID_ARG_2ND_NOT_ENCODED); + return $url; } } diff --git a/wcfsetup/install/files/lib/system/request/Route.class.php b/wcfsetup/install/files/lib/system/request/Route.class.php index 62fb7d5c5b..561d7661e5 100644 --- a/wcfsetup/install/files/lib/system/request/Route.class.php +++ b/wcfsetup/install/files/lib/system/request/Route.class.php @@ -180,6 +180,61 @@ class Route { return array_values($urlParts); } + /** + * Returns true if current route can handle the build request. + * + * @param array $components + * @return boolean + */ + public function canHandle(array $components) { + foreach ($this->routeSchema as $schemaPart) { + if (isset($components[$schemaPart])) { + // validate parameter against a regex pattern + if ($this->parameterOptions[$schemaPart]['regexPattern'] !== null) { + $pattern = '~^' . $this->parameterOptions[$schemaPart]['regexPattern'] . '$~'; + if (!preg_match($pattern, $components[$schemaPart])) { + return false; + } + } + } + else { + if (isset($this->parameterOptions[$schemaPart])) { + // default value is provided + if ($this->parameterOptions[$schemaPart]['default'] !== null) { + continue; + } + + // required parameter is missing + if (!$this->parameterOptions[$schemaPart]['isOptional']) { + return false; + } + } + } + } + + return true; + } + + /** + * Builds a link upon route components. + * + * @param array $components + * @return string + */ + public function buildLink(array $components) { + $link = 'index.php/'; + foreach ($this->routeSchema as $component) { + $link .= $components[$component] . '/'; + unset($components[$component]); + } + + if (!empty($components)) { + $link .= '?' . html_build_query($components, '', '&'); + } + + return $link; + } + /** * Returns true if route applies for ACP. * diff --git a/wcfsetup/install/files/lib/system/request/RouteHandler.class.php b/wcfsetup/install/files/lib/system/request/RouteHandler.class.php index bb0146e6c2..0d23509144 100644 --- a/wcfsetup/install/files/lib/system/request/RouteHandler.class.php +++ b/wcfsetup/install/files/lib/system/request/RouteHandler.class.php @@ -16,6 +16,12 @@ use wcf\system\SingletonFactory; * @category Community Framework */ class RouteHandler extends SingletonFactory { + /** + * router filter for ACP + * @var boolean + */ + protected $isACP = false; + /** * list of available routes * @var array @@ -70,10 +76,12 @@ class RouteHandler extends SingletonFactory { * @return boolean */ public function matches($isACP) { + $this->isACP = $isACP; + $pathInfo = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : ''; foreach ($this->routes as $route) { - if ($isACP != $route->isACP()) { + if ($this->isACP != $route->isACP()) { continue; } @@ -105,4 +113,25 @@ class RouteHandler extends SingletonFactory { $_REQUEST[$key] = $value; } } + + /** + * Builds a route based upon route components, this is nothing + * but a reverse lookup. + * + * @param array $components + * @return string + */ + public function buildRoute(array $components) { + foreach ($this->routes as $route) { + if ($this->isACP != $route->isACP()) { + continue; + } + + if ($route->canHandle($components)) { + return $route->buildLink($components); + } + } + + throw new SystemException("Unable to build route, no available route is satisfied."); + } } diff --git a/wcfsetup/install/files/lib/system/template/plugin/LinkBlockTemplatePlugin.class.php b/wcfsetup/install/files/lib/system/template/plugin/LinkBlockTemplatePlugin.class.php index 093dcee098..2c2fcefb93 100644 --- a/wcfsetup/install/files/lib/system/template/plugin/LinkBlockTemplatePlugin.class.php +++ b/wcfsetup/install/files/lib/system/template/plugin/LinkBlockTemplatePlugin.class.php @@ -27,12 +27,11 @@ class LinkBlockTemplatePlugin implements IBlockTemplatePlugin { * @see wcf\system\template\IBlockTemplatePlugin::execute() */ public function execute($tagArgs, $blockContent, TemplateEngine $tplObj) { - $application = 'wcf'; - if (!empty($tagArgs['application'])) { - $application = $tagArgs['application']; + if (!isset($tagArgs['application']) || empty($tagArgs['application'])) { + $tagArgs['application'] = 'wcf'; } - return LinkHandler::getInstance()->getLink($blockContent, $application); + return LinkHandler::getInstance()->getLink($blockContent, $tagArgs); } /** -- 2.20.1