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->standalone = trim($action['standalone']) === 'false' ? 'false' : 'true';
$action_info->check_csrf = (trim($action['check_csrf']) ?: trim($action['check-csrf'])) === '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->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'; $action_info->use_ssl = (trim($action['use_ssl']) ?: trim($action['use-ssl'])) === 'true' ? 'true' : 'false';
$info->action->{$action_name} = $action_info; $info->action->{$action_name} = $action_info;

View file

@ -2,6 +2,8 @@
namespace Rhymix\Framework; namespace Rhymix\Framework;
use function Complex\sec;
/** /**
* The router class. * The router class.
*/ */
@ -59,7 +61,8 @@ class Router
*/ */
protected static $_action_cache_prefix = array(); protected static $_action_cache_prefix = array();
protected static $_action_cache_module = 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(); protected static $_route_cache = array();
/** /**
@ -118,7 +121,7 @@ class Router
} }
// Try to detect the prefix. This might be $mid. // 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. // Separate the prefix and the internal part of the URL.
$prefix = $matches[1]; $prefix = $matches[1];
@ -139,7 +142,7 @@ class Router
} }
// Check other modules. // Check other modules.
$forwarded_routes = self::_getForwardedRoutes(); $forwarded_routes = self::_getForwardedRoutes('internal');
foreach ($forwarded_routes[$method] ?: [] as $regexp => $action) foreach ($forwarded_routes[$method] ?: [] as $regexp => $action)
{ {
if (preg_match($regexp, $internal_url, $matches)) 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. // Try XE-compatible global routes.
foreach (self::$_global_routes as $route_info) foreach (self::$_global_routes as $route_info)
{ {
@ -227,12 +245,12 @@ class Router
return self::_insertRouteVars(self::$_route_cache[$keys_string], $args); 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 $mid exists, try routes defined in the module.
if ($rewrite_level >= 2 && isset($args['mid'])) 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. // Get module action info.
$action_info = self::_getActionInfoByPrefix($args['mid']); $action_info = self::_getActionInfoByPrefix($args['mid']);
@ -252,7 +270,7 @@ class Router
} }
// Check other modules for $act. // Check other modules for $act.
$forwarded_routes = self::_getForwardedRoutes(); $forwarded_routes = self::_getForwardedRoutes('internal');
if (isset($forwarded_routes['reverse'][$act])) if (isset($forwarded_routes['reverse'][$act]))
{ {
$result = self::_getBestMatchingRoute($forwarded_routes['reverse'][$act], $args2); $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. // Try the generic mid/act pattern.
self::$_route_cache[$keys_string] = '$mid/$act'; self::$_route_cache[$keys_string] = '$mid/$act';
return $args['mid'] . '/' . $args['act'] . (count($args2) ? ('?' . http_build_query($args2)) : ''); 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. // Try XE-compatible global routes.
if ($rewrite_level >= 1) if ($rewrite_level >= 1)
{ {
@ -343,14 +365,26 @@ class Router
/** /**
* Get the list of routes that are registered for action-forward. * 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(); $action_forward = \ModuleModel::getActionForward();
foreach ($action_forward as $action_name => $action_info) foreach ($action_forward as $action_name => $action_info)
@ -359,12 +393,26 @@ class Router
{ {
foreach ($action_info->route_regexp as $regexp_info) 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> <module>
<grants /> <grants />
<actions> <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_searchAdminContent" type="view" admin_index="true" />
<action name="dispIntegration_searchAdminSkinInfo" type="view" /> <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; 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 // check route columns in action_forward table
if(!$oDB->isColumnExists('action_forward', 'route_regexp')) return true; if(!$oDB->isColumnExists('action_forward', 'route_regexp')) return true;
if(!$oDB->isColumnExists('action_forward', 'route_config')) 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'); $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 * Action forward finds and forwards if an action is not in the requested module
* This is used when installing a 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 = new stdClass();
$args->module = $module; $args->module = $module;
$args->type = $type; $args->type = $type;
$args->act = $act; $args->act = $act;
$args->route_regexp = $route_regexp; $args->route_regexp = serialize($route_regexp);
$args->route_config = $route_config; $args->route_config = serialize($route_config);
$args->global_route = $global_route === 'Y' ? 'Y' : 'N';
$output = executeQuery('module.insertActionForward', $args); $output = executeQuery('module.insertActionForward', $args);
Rhymix\Framework\Cache::delete('action_forward'); Rhymix\Framework\Cache::delete('action_forward');
@ -1337,6 +1338,7 @@ class moduleController extends module
'type' => $module_action_info->action->{$action_name}->type, 'type' => $module_action_info->action->{$action_name}->type,
'regexp' => array(), 'regexp' => array(),
'config' => $action_info->route, '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'] || 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); $output = $this->deleteActionForward($module_name, $route_info['type'], $action_name);
if (!$output->toBool()) if (!$output->toBool())
@ -1377,7 +1380,7 @@ class moduleController extends module
} }
$output = $this->insertActionForward($module_name, $route_info['type'], $action_name, $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()) if (!$output->toBool())
{ {
return $output; return $output;

View file

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

View file

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