Use action_forward to register standalone routes from all modules

This commit is contained in:
Kijin Sung 2020-06-17 16:56:42 +09:00
parent 5dcb0d332b
commit f92fc9c980
7 changed files with 162 additions and 59 deletions

View file

@ -59,6 +59,7 @@ 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 $_route_cache = array(); protected static $_route_cache = array();
/** /**
@ -136,8 +137,8 @@ class Router
} }
// Check other modules. // Check other modules.
$all_routes = self::_getAllCachedRoutes(); $forwarded_routes = self::_getForwardedRoutes();
foreach ($all_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))
{ {
@ -235,10 +236,10 @@ class Router
} }
// Check other modules for $act. // Check other modules for $act.
$all_routes = self::_getAllCachedRoutes(); $forwarded_routes = self::_getForwardedRoutes();
if (isset($all_routes->reverse[$act])) if (isset($forwarded_routes['reverse'][$act]))
{ {
$result = self::_getBestMatchingRoute($all_routes->reverse[$act], $args2); $result = self::_getBestMatchingRoute($forwarded_routes['reverse'][$act], $args2);
if ($result !== false) if ($result !== false)
{ {
self::$_route_cache[$keys_string] = '$mid/' . $result . '$act:delete'; self::$_route_cache[$keys_string] = '$mid/' . $result . '$act:delete';
@ -324,20 +325,30 @@ class Router
} }
/** /**
* Get the list of all cached routes from all modules. * Get the list of routes that are registered for action-forward.
* *
* @return object * @return object
*/ */
protected static function _getAllCachedRoutes() protected static function _getForwardedRoutes()
{ {
$cache_key = 'site_and_module:action_with_routes'; if (count(self::$_forwarded_cache))
$result = Cache::get($cache_key); {
if ($result === null) return self::$_forwarded_cache;
{ }
$result = (object)array('GET' => [], 'POST' => [], 'reverse' => []);
Cache::set($cache_key, $result, 0, true); $action_forward = \ModuleModel::getActionForward();
} foreach ($action_forward as $action_name => $action_info)
return $result; {
if ($action_info->route_regexp)
{
foreach ($action_info->route_regexp as $regexp_info)
{
self::$_forwarded_cache[$regexp_info[0]][$regexp_info[1]] = [$action_info->module, $action_name];
}
self::$_forwarded_cache['reverse'][$action_name] = $action_info->route_config;
}
}
return self::$_forwarded_cache;
} }
/** /**

View file

@ -24,7 +24,8 @@ class installAdminController extends install
$oInstallController = getController('install'); $oInstallController = getController('install');
$oInstallController->installModule($module_name, './modules/'.$module_name); $oInstallController->installModule($module_name, './modules/'.$module_name);
$oModuleController = getController('module');
$oModuleController->registerActionForwardRoutes($module_name);
$this->setMessage('success_installed'); $this->setMessage('success_installed');
} }
@ -41,13 +42,23 @@ class installAdminController extends install
if(!$oModule) throw new Rhymix\Framework\Exceptions\InvalidRequest; if(!$oModule) throw new Rhymix\Framework\Exceptions\InvalidRequest;
Rhymix\Framework\Session::close(); Rhymix\Framework\Session::close();
$output = $oModule->moduleUpdate(); $output = $oModule->moduleUpdate();
Rhymix\Framework\Session::start();
if($output instanceof BaseObject && !$output->toBool()) if($output instanceof BaseObject && !$output->toBool())
{ {
Rhymix\Framework\Session::start();
return $output; return $output;
} }
$oModuleController = getController('module');
$oModuleController->registerActionForwardRoutes($module_name);
if($output instanceof BaseObject && !$output->toBool())
{
Rhymix\Framework\Session::start();
return $output;
}
Rhymix\Framework\Session::start();
$this->setMessage('success_updated'); $this->setMessage('success_updated');
} }

View file

@ -133,7 +133,6 @@ class module extends ModuleObject
} }
// check route columns in action_forward table // check route columns in action_forward table
if(!$oDB->isColumnExists('action_forward', 'route_method')) return true;
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;
} }
@ -455,13 +454,9 @@ class module extends ModuleObject
} }
// check route columns in action_forward table // check route columns in action_forward table
if(!$oDB->isColumnExists('action_forward', 'route_method'))
{
$oDB->addColumn('action_forward', 'route_method', 'varchar', 30);
}
if(!$oDB->isColumnExists('action_forward', 'route_regexp')) if(!$oDB->isColumnExists('action_forward', 'route_regexp'))
{ {
$oDB->addColumn('action_forward', 'route_regexp', 'varchar', 180); $oDB->addColumn('action_forward', 'route_regexp', 'text');
} }
if(!$oDB->isColumnExists('action_forward', 'route_config')) if(!$oDB->isColumnExists('action_forward', 'route_config'))
{ {

View file

@ -19,13 +19,12 @@ 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_method = null, $route_regexp = null, $route_config = null) function insertActionForward($module, $type, $act, $route_regexp = null, $route_config = null)
{ {
$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_method = $route_method;
$args->route_regexp = $route_regexp; $args->route_regexp = $route_regexp;
$args->route_config = $route_config; $args->route_config = $route_config;
$output = executeQuery('module.insertActionForward', $args); $output = executeQuery('module.insertActionForward', $args);
@ -1291,6 +1290,78 @@ class moduleController extends module
Rhymix\Framework\Cache::clearGroup('site_and_module'); Rhymix\Framework\Cache::clearGroup('site_and_module');
return $output; return $output;
} }
/**
* Check if all action-forwardable routes are registered. If not, register them.
*
* @param string $module_name
* @return object
*/
public function registerActionForwardRoutes(string $module_name)
{
$action_forward = ModuleModel::getActionForward();
$module_action_info = ModuleModel::getModuleActionXml($module_name);
// Get the list of forwardable actions and their routes.
$forwardable_routes = array();
foreach ($module_action_info->action ?: [] as $action_name => $action_info)
{
if (count($action_info->route) && $action_info->standalone !== 'false')
{
$forwardable_routes[$action_name] = array(
'type' => $module_action_info->action->{$action_name}->type,
'regexp' => array(),
'config' => $action_info->route,
);
}
}
foreach ($module_action_info->route->GET as $regexp => $action_name)
{
if (isset($forwardable_routes[$action_name]))
{
$forwardable_routes[$action_name]['regexp'][] = ['GET', $regexp];
}
}
foreach ($module_action_info->route->POST as $regexp => $action_name)
{
if (isset($forwardable_routes[$action_name]))
{
$forwardable_routes[$action_name]['regexp'][] = ['POST', $regexp];
}
}
// Insert or delete from the action_forward table.
foreach ($forwardable_routes as $action_name => $route_info)
{
if (!isset($action_forward[$action_name]))
{
$output = $this->insertActionForward($module_name, $route_info['type'], $action_name,
serialize($route_info['regexp']), serialize($route_info['config']));
if (!$output->toBool())
{
return $output;
}
}
elseif ($action_forward[$action_name]->route_regexp !== $route_info['regexp'] ||
$action_forward[$action_name]->route_config !== $route_info['config'])
{
$output = $this->deleteActionForward($module_name, $route_info['type'], $action_name);
if (!$output->toBool())
{
return $output;
}
$output = $this->insertActionForward($module_name, $route_info['type'], $action_name,
serialize($route_info['regexp']), serialize($route_info['config']));
if (!$output->toBool())
{
return $output;
}
}
}
return new BaseObject();
}
} }
/* End of file module.controller.php */ /* End of file module.controller.php */
/* Location: ./modules/module/module.controller.php */ /* Location: ./modules/module/module.controller.php */

View file

@ -567,7 +567,7 @@ class moduleModel extends module
/** /**
* @brief Get forward value by the value of act * @brief Get forward value by the value of act
*/ */
public static function getActionForward($act) public static function getActionForward($act = null)
{ {
$action_forward = Rhymix\Framework\Cache::get('action_forward'); $action_forward = Rhymix\Framework\Cache::get('action_forward');
if($action_forward === null) if($action_forward === null)
@ -582,12 +582,18 @@ class moduleModel extends module
$action_forward = array(); $action_forward = array();
foreach($output->data as $item) foreach($output->data as $item)
{ {
if ($item->route_regexp) $item->route_regexp = unserialize($item->route_regexp);
if ($item->route_config) $item->route_config = unserialize($item->route_config);
$action_forward[$item->act] = $item; $action_forward[$item->act] = $item;
} }
Rhymix\Framework\Cache::set('action_forward', $action_forward, 0, true); Rhymix\Framework\Cache::set('action_forward', $action_forward, 0, true);
} }
if(!isset($act))
{
return $action_forward;
}
if(!isset($action_forward[$act])) if(!isset($action_forward[$act]))
{ {
return; return;
@ -723,30 +729,7 @@ class moduleModel extends module
$info = Rhymix\Framework\Cache::get($cache_key); $info = Rhymix\Framework\Cache::get($cache_key);
if($info === null) if($info === null)
{ {
// Load the XML file.
$info = Rhymix\Framework\Parsers\ModuleActionParser::loadXML($xml_file); $info = Rhymix\Framework\Parsers\ModuleActionParser::loadXML($xml_file);
// Add all routes from the module to a global list.
$action_cache_key = 'site_and_module:action_with_routes';
$action_with_routes = Rhymix\Framework\Cache::get($action_cache_key) ?: (object)array('GET' => [], 'POST' => [], 'reverse' => []);
foreach ($info->route->GET as $regexp => $action)
{
$action_with_routes->GET[$regexp] = [$module, $action];
}
foreach ($info->route->POST as $regexp => $action)
{
$action_with_routes->POST[$regexp] = [$module, $action];
}
foreach ($info->action as $action_name => $action_info)
{
if (count($action_info->route) && $action_info->standalone !== 'false')
{
$action_with_routes->reverse[$action_name] = $action_info->route;
}
}
// Set cache entries.
Rhymix\Framework\Cache::set($action_cache_key, $action_with_routes, 0, true);
Rhymix\Framework\Cache::set($cache_key, $info, 0, true); Rhymix\Framework\Cache::set($cache_key, $info, 0, true);
} }
@ -1361,12 +1344,12 @@ class moduleModel extends module
$searched_count = count($searched_list); $searched_count = count($searched_list);
if(!$searched_count) return; if(!$searched_count) return;
// Get action forward
$action_forward = self::getActionForward();
for($i=0;$i<$searched_count;$i++) foreach ($searched_list as $module_name)
{ {
// module name
$module_name = $searched_list[$i];
$path = ModuleHandler::getModulePath($module_name); $path = ModuleHandler::getModulePath($module_name);
if(!is_dir(FileHandler::getRealPath($path))) continue; if(!is_dir(FileHandler::getRealPath($path))) continue;
@ -1403,16 +1386,50 @@ class moduleModel extends module
{ {
$info->need_install = false; $info->need_install = false;
} }
// Check if it is upgraded to module.class.php on each module // Check if it is upgraded to module.class.php on each module
$oDummy = null;
$oDummy = getModule($module_name, 'class'); $oDummy = getModule($module_name, 'class');
if($oDummy && method_exists($oDummy, "checkUpdate")) if($oDummy && method_exists($oDummy, "checkUpdate"))
{ {
$info->need_update = $oDummy->checkUpdate(); $info->need_update = $oDummy->checkUpdate();
} }
else unset($oDummy);
// Check if all action-forwardable routes are registered
$module_action_info = self::getModuleActionXml($module_name);
$forwardable_routes = array();
foreach ($module_action_info->action ?: [] as $action_name => $action_info)
{ {
continue; if (count($action_info->route) && $action_info->standalone !== 'false')
{
$forwardable_routes[$action_name] = array(
'regexp' => array(),
'config' => $action_info->route,
);
}
}
foreach ($module_action_info->route->GET as $regexp => $action_name)
{
if (isset($forwardable_routes[$action_name]))
{
$forwardable_routes[$action_name]['regexp'][] = ['GET', $regexp];
}
}
foreach ($module_action_info->route->POST as $regexp => $action_name)
{
if (isset($forwardable_routes[$action_name]))
{
$forwardable_routes[$action_name]['regexp'][] = ['POST', $regexp];
}
}
foreach ($forwardable_routes as $action_name => $route_info)
{
if (!isset($action_forward[$action_name]) ||
$action_forward[$action_name]->route_regexp !== $route_info['regexp'] ||
$action_forward[$action_name]->route_config !== $route_info['config'])
{
$info->need_update = true;
}
} }
} }
$list[] = $info; $list[] = $info;

View file

@ -6,7 +6,6 @@
<column name="act" var="act" notnull="notnull" /> <column name="act" var="act" notnull="notnull" />
<column name="module" var="module" notnull="notnull" /> <column name="module" var="module" notnull="notnull" />
<column name="type" var="type" notnull="notnull" /> <column name="type" var="type" notnull="notnull" />
<column name="route_method" var="route_method" />
<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" />
</columns> </columns>

View file

@ -2,7 +2,6 @@
<column name="act" type="varchar" size="80" notnull="notnull" primary_key="primary_key" /> <column name="act" type="varchar" size="80" notnull="notnull" primary_key="primary_key" />
<column name="module" type="varchar" size="60" notnull="notnull" /> <column name="module" type="varchar" size="60" notnull="notnull" />
<column name="type" type="varchar" size="15" notnull="notnull" /> <column name="type" type="varchar" size="15" notnull="notnull" />
<column name="route_method" type="varchar" size="30" /> <column name="route_regexp" type="text" />
<column name="route_regexp" type="varchar" size="180" />
<column name="route_config" type="text" /> <column name="route_config" type="text" />
</table> </table>