From bf8d2c8b09fce8a6c818339d429c3aab5dc4575c Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sat, 13 Jun 2020 11:48:58 +0900 Subject: [PATCH] Improve handling of multiple routes per action --- .../framework/parsers/moduleactionparser.php | 23 +++++++++++++------ common/framework/router.php | 15 ++++++++---- modules/board/conf/module.xml | 20 ++++++++++------ 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/common/framework/parsers/moduleactionparser.php b/common/framework/parsers/moduleactionparser.php index 5a3ef5f58..caa02a983 100644 --- a/common/framework/parsers/moduleactionparser.php +++ b/common/framework/parsers/moduleactionparser.php @@ -18,6 +18,7 @@ class ModuleActionParser 'alphanum' => '[a-zA-Z0-9]+', 'hex' => '[0-9a-f]+', 'word' => '[a-zA-Z0-9_]+', + 'any' => '[^/]+', ); /** @@ -106,17 +107,22 @@ class ModuleActionParser } // Parse routes. - $route = trim($action['route']); + $route_attr = trim($action['route']); + $route_tags = $action->route; $method = trim($action['method']); $route_arg = []; - if ($route) + if ($route_attr || count($route_tags)) { $methods = $method ? explode('|', strtoupper($method)) : (starts_with('proc', $action_name) ? ['POST'] : ['GET']); - $routes = explode_with_escape('|', $route); + $routes = $route_attr ? explode_with_escape('|', $route_attr) : array(); + foreach ($route_tags as $route_tag) + { + $routes[] = trim($route_tag['route']); + } foreach ($routes as $route) { $route_info = self::analyzeRoute($route); - $route_arg[$route] = $route_info->vars; + $route_arg[$route_info->route] = $route_info->vars; foreach ($methods as $method) { $info->route->{$method}[$route_info->regexp] = $action_name; @@ -180,16 +186,18 @@ class ModuleActionParser $var_regexp = '#\\$([a-zA-Z0-9_]+)(?::(' . implode('|', array_keys(self::$_shortcuts)) . '))?#'; $vars = array(); $regexp = preg_replace_callback($var_regexp, function($match) use(&$vars) { - if (isset($match[2]) && isset(self::$_shortcuts[$match[2]])) + if (isset($match[2])) { + $var_type = $match[2]; $var_pattern = self::$_shortcuts[$match[2]]; } else { - $var_pattern = ends_with('_srl', $match[1]) ? '[0-9]+' : '[^/]+'; + $var_type = ends_with('_srl', $match[1]) ? 'number' : 'any'; + $var_pattern = self::$_shortcuts[$var_type]; } $named_group = '(?P<' . $match[1] . '>' . $var_pattern . ')'; - $vars[] = $match[1]; + $vars[$match[1]] = $var_type; return $named_group; }, $route); @@ -198,6 +206,7 @@ class ModuleActionParser // Return the regexp and variable list. $result = new \stdClass; + $result->route = preg_replace($var_regexp, '\\$$1', $route); $result->regexp = $regexp; $result->vars = $vars; return $result; diff --git a/common/framework/router.php b/common/framework/router.php index 0aa01c1c3..10edae3ab 100644 --- a/common/framework/router.php +++ b/common/framework/router.php @@ -158,15 +158,20 @@ class Router return urlencode($args[$keys[0]]); } - // If $mid and $act exist, try routes defined in the module. + // If $mid exists, try routes defined in the module. if (isset($args['mid']) && isset($args['act']) && $rewrite_level == 2) { // Remove $mid and $act from arguments and work with the remainder. $remaining_args = array_diff_key($args, ['mid' => 'mid', 'act' => 'act']); - // Check if $act has any routes defined. + // Get module action info. $action_info = self::_getModuleActionInfo($args['mid']); - $action = $action_info->action->{$args['act']}; + + // If there is no $act, use the default action. + $act = isset($args['act']) ? $args['act'] : $action_info->default_index_act; + + // Check if $act has any routes defined. + $action = $action_info->action->{$act}; if ($action->route) { // If the action only has one route, select it. @@ -182,7 +187,7 @@ class Router $reordered_routes = array(); foreach ($action->route as $route => $route_vars) { - $matched_arguments = array_intersect_key(array_combine($route_vars, $route_vars), $remaining_args); + $matched_arguments = array_intersect_key($route_vars, $remaining_args); if (count($matched_arguments) === count($route_vars)) { $reordered_routes[$route] = count($matched_arguments); @@ -214,6 +219,8 @@ class Router return $args['mid'] . '/' . $args['act'] . (count($remaining_args) ? ('?' . http_build_query($remaining_args)) : ''); } + // Try XE-compatible global routes. + // If no route matches, just create a query string. return 'index.php?' . http_build_query($args); } diff --git a/modules/board/conf/module.xml b/modules/board/conf/module.xml index 63fe0b78f..d7962d6b2 100644 --- a/modules/board/conf/module.xml +++ b/modules/board/conf/module.xml @@ -56,13 +56,19 @@ - - - - - - - + + + + + + + + + + + + +