Support global routes

This commit is contained in:
Kijin Sung 2020-06-18 16:36:27 +09:00
parent 7e47c1cb8a
commit c8a6b8de79
8 changed files with 94 additions and 41 deletions

View file

@ -126,6 +126,7 @@ class ModuleActionParser
$action_info->standalone = trim($action['standalone']) === 'false' ? 'false' : 'true';
$action_info->check_csrf = (trim($action['check_csrf']) ?: trim($action['check-csrf'])) === 'false' ? 'false' : 'true';
$action_info->meta_noindex = (trim($action['meta_noindex']) ?: trim($action['meta-noindex'])) === 'true' ? 'true' : 'false';
$action_info->global_route = (trim($action['global_route']) ?: trim($action['global-route'])) === 'true' ? 'true' : 'false';
$action_info->use_ssl = (trim($action['use_ssl']) ?: trim($action['use-ssl'])) === 'true' ? 'true' : 'false';
$info->action->{$action_name} = $action_info;

View file

@ -2,6 +2,8 @@
namespace Rhymix\Framework;
use function Complex\sec;
/**
* The router class.
*/
@ -59,7 +61,8 @@ class Router
*/
protected static $_action_cache_prefix = array();
protected static $_action_cache_module = array();
protected static $_forwarded_cache = array();
protected static $_global_forwarded_cache = array();
protected static $_internal_forwarded_cache = array();
protected static $_route_cache = array();
/**
@ -118,7 +121,7 @@ class Router
}
// Try to detect the prefix. This might be $mid.
if ($rewrite_level > 1 && preg_match('#^([a-zA-Z0-9_-]+)(?:/(.*))?#s', $url, $matches))
if ($rewrite_level >= 2 && preg_match('#^([a-zA-Z0-9_-]+)(?:/(.*))?#s', $url, $matches))
{
// Separate the prefix and the internal part of the URL.
$prefix = $matches[1];
@ -139,7 +142,7 @@ class Router
}
// Check other modules.
$forwarded_routes = self::_getForwardedRoutes();
$forwarded_routes = self::_getForwardedRoutes('internal');
foreach ($forwarded_routes[$method] ?: [] as $regexp => $action)
{
if (preg_match($regexp, $internal_url, $matches))
@ -166,6 +169,21 @@ class Router
}
}
// Try registered global routes.
if ($rewrite_level >= 2)
{
$global_routes = self::_getForwardedRoutes('global');
foreach ($global_routes[$method] ?: [] as $regexp => $action)
{
if (preg_match($regexp, $url, $matches))
{
$matches = array_filter($matches, 'is_string', \ARRAY_FILTER_USE_KEY);
$allargs = array_merge(['act' => $action[1]], $matches, $args);
return (object)['status' => 200, 'url' => $url, 'args' => $allargs];
}
}
}
// Try XE-compatible global routes.
foreach (self::$_global_routes as $route_info)
{
@ -227,12 +245,12 @@ class Router
return self::_insertRouteVars(self::$_route_cache[$keys_string], $args);
}
// Remove $mid and $act from arguments and work with the remainder.
$args2 = $args; unset($args2['mid'], $args2['act']);
// If $mid exists, try routes defined in the module.
if ($rewrite_level >= 2 && isset($args['mid']))
{
// Remove $mid from arguments and work with the remainder.
$args2 = $args; unset($args2['mid'], $args2['act']);
// Get module action info.
$action_info = self::_getActionInfoByPrefix($args['mid']);
@ -252,7 +270,7 @@ class Router
}
// Check other modules for $act.
$forwarded_routes = self::_getForwardedRoutes();
$forwarded_routes = self::_getForwardedRoutes('internal');
if (isset($forwarded_routes['reverse'][$act]))
{
$result = self::_getBestMatchingRoute($forwarded_routes['reverse'][$act], $args2);
@ -263,22 +281,26 @@ class Router
}
}
// Check XE-compatible routes that start with $mid and contain no $act.
if (!isset($args['act']) || ($args['act'] === 'rss' || $args['act'] === 'atom' || $args['act'] === 'api'))
{
$result = self::_getBestMatchingRoute(self::$_global_routes, $args2);
if ($result !== false)
{
self::$_route_cache[$keys_string] = $result;
return self::_insertRouteVars($result, $args2);
}
}
// Try the generic mid/act pattern.
self::$_route_cache[$keys_string] = '$mid/$act';
return $args['mid'] . '/' . $args['act'] . (count($args2) ? ('?' . http_build_query($args2)) : '');
}
// Try registered global routes.
if ($rewrite_level >= 2 && isset($args['act']))
{
$global_routes = self::_getForwardedRoutes('global');
if (isset($global_routes['reverse'][$args['act']]))
{
$result = self::_getBestMatchingRoute($global_routes['reverse'][$args['act']], $args2);
if ($result !== false)
{
self::$_route_cache[$keys_string] = $result . '$act:delete';
return self::_insertRouteVars($result, $args2);
}
}
}
// Try XE-compatible global routes.
if ($rewrite_level >= 1)
{
@ -343,14 +365,26 @@ class Router
/**
* Get the list of routes that are registered for action-forward.
*
* @return object
* @param string $type
* @return array
*/
protected static function _getForwardedRoutes()
protected static function _getForwardedRoutes(string $type): array
{
if (count(self::$_forwarded_cache))
if ($type === 'internal' && count(self::$_internal_forwarded_cache))
{
return self::$_forwarded_cache;
return self::$_internal_forwarded_cache;
}
if ($type === 'global' && count(self::$_global_forwarded_cache))
{
return self::$_global_forwarded_cache;
}
self::$_global_forwarded_cache['GET'] = array();
self::$_global_forwarded_cache['POST'] = array();
self::$_global_forwarded_cache['reverse'] = array();
self::$_internal_forwarded_cache['GET'] = array();
self::$_internal_forwarded_cache['POST'] = array();
self::$_internal_forwarded_cache['reverse'] = array();
$action_forward = \ModuleModel::getActionForward();
foreach ($action_forward as $action_name => $action_info)
@ -359,12 +393,26 @@ class Router
{
foreach ($action_info->route_regexp as $regexp_info)
{
self::$_forwarded_cache[$regexp_info[0]][$regexp_info[1]] = [$action_info->module, $action_name];
if ($action_info->global_route === 'Y')
{
self::$_global_forwarded_cache[$regexp_info[0]][$regexp_info[1]] = [$action_info->module, $action_name];
}
else
{
self::$_internal_forwarded_cache[$regexp_info[0]][$regexp_info[1]] = [$action_info->module, $action_name];
}
}
if ($action_info->global_route === 'Y')
{
self::$_global_forwarded_cache['reverse'][$action_name] = $action_info->route_config;
}
else
{
self::$_internal_forwarded_cache['reverse'][$action_name] = $action_info->route_config;
}
self::$_forwarded_cache['reverse'][$action_name] = $action_info->route_config;
}
}
return self::$_forwarded_cache;
return $type === 'internal' ? self::$_internal_forwarded_cache : self::$_global_forwarded_cache;
}
/**

View file

@ -2,7 +2,11 @@
<module>
<grants />
<actions>
<action name="IS" type="view" meta-noindex="true" />
<action name="IS" type="view" meta-noindex="true" global-route="true">
<route route="search" />
<route route="search/$search_keyword" />
<route route="search/$search_target:word/$search_keyword" />
</action>
<action name="dispIntegration_searchAdminContent" type="view" admin_index="true" />
<action name="dispIntegration_searchAdminSkinInfo" type="view" />

View file

@ -39,10 +39,6 @@ class integration_search extends ModuleObject
}
}
if (!$oModuleModel->getActionForward('IS'))
{
return true;
}
return false;
}
@ -70,12 +66,6 @@ class integration_search extends ModuleObject
}
}
}
if (!$oModuleModel->getActionForward('IS'))
{
$oModuleController = getController('module');
$oModuleController->insertActionForward('integration_search', 'view', 'IS');
}
}
/**

View file

@ -135,6 +135,7 @@ class module extends ModuleObject
// check route columns in action_forward table
if(!$oDB->isColumnExists('action_forward', 'route_regexp')) return true;
if(!$oDB->isColumnExists('action_forward', 'route_config')) return true;
if(!$oDB->isColumnExists('action_forward', 'global_route')) return true;
}
/**
@ -462,6 +463,10 @@ class module extends ModuleObject
{
$oDB->addColumn('action_forward', 'route_config', 'text');
}
if(!$oDB->isColumnExists('action_forward', 'global_route'))
{
$oDB->addColumn('action_forward', 'global_route', 'char', 1, 'N', true);
}
}
/**

View file

@ -19,14 +19,15 @@ class moduleController extends module
* Action forward finds and forwards if an action is not in the requested module
* This is used when installing a module
*/
function insertActionForward($module, $type, $act, $route_regexp = null, $route_config = null)
function insertActionForward($module, $type, $act, $route_regexp = null, $route_config = null, $global_route = 'N')
{
$args = new stdClass();
$args->module = $module;
$args->type = $type;
$args->act = $act;
$args->route_regexp = $route_regexp;
$args->route_config = $route_config;
$args->route_regexp = serialize($route_regexp);
$args->route_config = serialize($route_config);
$args->global_route = $global_route === 'Y' ? 'Y' : 'N';
$output = executeQuery('module.insertActionForward', $args);
Rhymix\Framework\Cache::delete('action_forward');
@ -1337,6 +1338,7 @@ class moduleController extends module
'type' => $module_action_info->action->{$action_name}->type,
'regexp' => array(),
'config' => $action_info->route,
'global_route' => $action_info->global_route ? 'Y' : 'N',
);
}
}
@ -1368,7 +1370,8 @@ class moduleController extends module
}
}
elseif ($action_forward[$action_name]->route_regexp !== $route_info['regexp'] ||
$action_forward[$action_name]->route_config !== $route_info['config'])
$action_forward[$action_name]->route_config !== $route_info['config'] ||
$action_forward[$action_name]->global_route !== $route_info['global_route'])
{
$output = $this->deleteActionForward($module_name, $route_info['type'], $action_name);
if (!$output->toBool())
@ -1377,7 +1380,7 @@ class moduleController extends module
}
$output = $this->insertActionForward($module_name, $route_info['type'], $action_name,
serialize($route_info['regexp']), serialize($route_info['config']));
$route_info['regexp'], $route_info['config'], $route_info['global_route']);
if (!$output->toBool())
{
return $output;

View file

@ -8,5 +8,6 @@
<column name="type" var="type" notnull="notnull" />
<column name="route_regexp" var="route_regexp" />
<column name="route_config" var="route_config" />
<column name="global_route" var="global_route" default="N" />
</columns>
</query>

View file

@ -4,4 +4,5 @@
<column name="type" type="varchar" size="15" notnull="notnull" />
<column name="route_regexp" type="text" />
<column name="route_config" type="text" />
<column name="global_route" type="char" size="1" notnull="notnull" default="N" />
</table>