diff --git a/common/framework/parsers/moduleactionparser.php b/common/framework/parsers/moduleactionparser.php new file mode 100644 index 000000000..158ae958d --- /dev/null +++ b/common/framework/parsers/moduleactionparser.php @@ -0,0 +1,161 @@ +admin_index_act = ''; + $info->default_index_act = ''; + $info->setup_index_act = ''; + $info->simple_setup_index_act = ''; + $info->action = new \stdClass; + $info->menu = new \stdClass; + $info->grant = new \stdClass; + $info->permission = new \stdClass; + $info->permission_check = new \stdClass; + + // Parse grants. + foreach ($xml->grants->grant as $grant) + { + $grant_info = new \stdClass; + $grant_info->title = self::_getElementsByLang($grant, 'title', $lang); + $grant_info->default = trim($grant['default']); + $grant_name = trim($grant['name']); + $info->grant->{$grant_name} = $grant_info; + } + + // Parse permissions. + foreach ($xml->permissions->permission as $permission) + { + $action_name = trim($permission['action']); + $permission = trim($permission['target']); + $info->permission->{$action_name} = $permission; + + $check = new \stdClass; + $check->key = trim($permission['check_var']) ?: trim($permission['check-var']); + $check->type = trim($permission['check_type']) ?: trim($permission['check-type']); + $info->permission_check->{$action_name} = $check; + } + + // Parse menus. + foreach ($xml->menus->menu as $menu) + { + $menu_info = new \stdClass; + $menu_info->title = self::_getElementsByLang($menu, 'title', $lang); + $menu_info->index = null; + $menu_info->acts = array(); + $menu_info->type = trim($menu['type']); + $menu_name = trim($menu['name']); + $info->menu->{$menu_name} = $menu_info; + } + + // Parse actions. + foreach ($xml->actions->action as $action) + { + $action_name = trim($action['name']); + $permission = trim($action['permission']); + if ($permission) + { + $info->permission->{$action_name} = $permission; + if (isset($info->permission_check->{$action_name})) + { + $info->permission_check->{$action_name} = new \stdClass; + } + $info->permission_check->{$action_name}->key = trim($action['check_var']) ?: trim($action['check-var']); + $info->permission_check->{$action_name}->type = trim($action['check_type']) ?: trim($action['check-type']); + } + + $action_info = new \stdClass; + $action_info->type = trim($action['type']); + $action_info->grant = trim($action['grant']) ?: 'guest'; + $action_info->standalone = trim($action['standalone']) === 'false' ? 'false' : 'true'; + $action_info->ruleset = trim($action['ruleset']); + $action_info->method = trim($action['method']); + $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'; + $info->action->{$action_name} = $action_info; + + $menu_name = trim($action['menu_name']); + if ($menu_name) + { + $info->menu->{$menu_name}->acts[] = $action_name; + if (toBool($action['menu_index'])) + { + $info->menu->{$menu_name}->index = $action_name; + } + } + if (toBool($action['index'])) + { + $info->default_index_act = $action_name; + } + if (toBool($action['admin_index'])) + { + $info->admin_index_act = $action_name; + } + if (toBool($action['setup_index'])) + { + $info->setup_index_act = $action_name; + } + if (toBool($action['simple_setup_index'])) + { + $info->simple_setup_index_act = $action_name; + } + } + + // Return the complete result. + return $info; + } + + /** + * Get child elements that match a language. + * + * @param SimpleXMLElement $parent + * @param string $tag_name + * @param string $lang + * @return string|null + */ + protected static function _getElementsByLang(\SimpleXMLElement $parent, string $tag_name, string $lang): ?string + { + // If there is a child element that matches the language, return it. + foreach ($parent->{$tag_name} as $child) + { + $attribs = $child->attributes('xml', true); + if (strval($attribs['lang']) === $lang) + { + return trim($child); + } + } + + // Otherwise, return the first child element. + foreach ($parent->{$tag_name} as $child) + { + return trim($child); + } + + // If there are no child elements, return null. + return null; + } +} diff --git a/common/framework/parsers/moduleinfoparser.php b/common/framework/parsers/moduleinfoparser.php new file mode 100644 index 000000000..22144e6cf --- /dev/null +++ b/common/framework/parsers/moduleinfoparser.php @@ -0,0 +1,120 @@ +title = self::_getElementsByLang($xml, 'title', $lang); + $info->description = self::_getElementsByLang($xml, 'description', $lang); + $info->version = trim($xml->version); + $info->homepage = trim($xml->homepage); + $info->category = trim($xml->category) ?: 'service'; + $info->date = date('Ymd', strtotime($xml->date . 'T12:00:00Z')); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link']); + $info->author = array(); + + foreach ($xml->author as $author) + { + $author_info = new \stdClass; + $author_info->name = self::_getElementsByLang($author, 'name', $lang); + $author_info->email_address = trim($author['email_address']); + $author_info->homepage = trim($author['link']); + $info->author[] = $author_info; + } + } + + // Parse version 0.1 + else + { + $info->title = self::_getElementsByLang($xml, 'title', $lang); + $info->description = self::_getElementsByLang($xml->author, 'description', $lang); + $info->version = trim($xml['version']); + $info->homepage = trim($xml->homepage); + $info->category = trim($xml['category']) ?: 'service'; + $info->date = date('Ymd', strtotime($xml->author['date'] . 'T12:00:00Z')); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link']); + $info->author = array(); + + foreach ($xml->author as $author) + { + $author_info = new \stdClass; + $author_info->name = self::_getElementsByLang($author, 'name', $lang); + $author_info->email_address = trim($author['email_address']); + $author_info->homepage = trim($author['link']); + $info->author[] = $author_info; + } + } + + // Add information about actions. + $action_info = ModuleActionParser::loadXML(strtr($filename, ['info.xml' => 'module.xml'])); + $info->admin_index_act = $action_info->admin_index_act; + $info->default_index_act = $action_info->default_index_act; + $info->setup_index_act = $action_info->setup_index_act; + $info->simple_setup_index_act = $action_info->simple_setup_index_act; + + // Return the complete result. + return $info; + } + + /** + * Get child elements that match a language. + * + * @param SimpleXMLElement $parent + * @param string $tag_name + * @param string $lang + * @return string|null + */ + protected static function _getElementsByLang(\SimpleXMLElement $parent, string $tag_name, string $lang): ?string + { + // If there is a child element that matches the language, return it. + foreach ($parent->{$tag_name} as $child) + { + $attribs = $child->attributes('xml', true); + if (strval($attribs['lang']) === $lang) + { + return trim($child); + } + } + + // Otherwise, return the first child element. + foreach ($parent->{$tag_name} as $child) + { + return trim($child); + } + + // If there are no child elements, return null. + return null; + } +} diff --git a/modules/module/module.model.php b/modules/module/module.model.php index c114622d7..de077e463 100644 --- a/modules/module/module.model.php +++ b/modules/module/module.model.php @@ -686,73 +686,24 @@ class moduleModel extends module */ public static function getModuleInfoXml($module) { - // Get a path of the requested module. Return if not exists. + // Check the path and XML file name. $module_path = ModuleHandler::getModulePath($module); - if(!$module_path) return; - // Read the xml file for module skin information - $xml_file = sprintf("%s/conf/info.xml", $module_path); - if(!file_exists($xml_file)) return; - - $oXmlParser = new XmlParser(); - $tmp_xml_obj = $oXmlParser->loadXmlFile($xml_file); - $xml_obj = $tmp_xml_obj->module; - - if(!$xml_obj) return; - - // Module Information - $module_info = new stdClass(); - if($xml_obj->version && $xml_obj->attrs->version == '0.2') + if (!$module_path) return; + $xml_file = $module_path . 'conf/info.xml'; + if (!file_exists($xml_file)) return; + + // Load the XML file and cache the definition. + $mtime1 = filemtime($xml_file); + $mtime2 = filemtime($module_path . 'conf/module.xml'); + $cache_key = sprintf('site_and_module:module_info_xml:%s:%d:%d', $module, $mtime1, $mtime2); + $info = Rhymix\Framework\Cache::get($cache_key); + if($info === null) { - // module format 0.2 - $module_info->title = $xml_obj->title->body; - $module_info->description = $xml_obj->description->body; - $module_info->version = $xml_obj->version->body; - $module_info->homepage = $xml_obj->link->body; - $module_info->category = $xml_obj->category->body; - if(!$module_info->category) $module_info->category = 'service'; - $date_obj = (object)array('y' => 0, 'm' => 0, 'd' => 0); - sscanf($xml_obj->date->body, '%d-%d-%d', $date_obj->y, $date_obj->m, $date_obj->d); - $module_info->date = sprintf('%04d%02d%02d', $date_obj->y, $date_obj->m, $date_obj->d); - $module_info->license = $xml_obj->license->body; - $module_info->license_link = $xml_obj->license->attrs->link; - - if(!is_array($xml_obj->author)) $author_list[] = $xml_obj->author; - else $author_list = $xml_obj->author; - - foreach($author_list as $author) - { - $author_obj = new stdClass(); - $author_obj->name = $author->name->body; - $author_obj->email_address = $author->attrs->email_address; - $author_obj->homepage = $author->attrs->link; - $module_info->author[] = $author_obj; - } + $info = Rhymix\Framework\Parsers\ModuleInfoParser::loadXML($xml_file); + Rhymix\Framework\Cache::set($cache_key, $info); } - else - { - // module format 0.1 - $module_info->title = $xml_obj->title->body; - $module_info->description = $xml_obj->author->description->body; - $module_info->version = $xml_obj->attrs->version; - $module_info->category = $xml_obj->attrs->category; - if(!$module_info->category) $module_info->category = 'service'; - $date_obj = (object)array('y' => 0, 'm' => 0, 'd' => 0); - sscanf($xml_obj->author->attrs->date, '%d. %d. %d', $date_obj->y, $date_obj->m, $date_obj->d); - $module_info->date = sprintf('%04d%02d%02d', $date_obj->y, $date_obj->m, $date_obj->d); - $author_obj = new stdClass(); - $author_obj->name = $xml_obj->author->name->body; - $author_obj->email_address = $xml_obj->author->attrs->email_address; - $author_obj->homepage = $xml_obj->author->attrs->link; - $module_info->author[] = $author_obj; - } - // Add admin_index by using action information - $action_info = self::getModuleActionXml($module); - $module_info->admin_index_act = $action_info->admin_index_act; - $module_info->default_index_act = $action_info->default_index_act; - $module_info->setup_index_act = $action_info->setup_index_act; - $module_info->simple_setup_index_act = $action_info->simple_setup_index_act; - - return $module_info; + + return $info; } /** @@ -763,242 +714,23 @@ class moduleModel extends module */ public static function getModuleActionXml($module) { - // Get a path of the requested module. Return if not exists. - $class_path = ModuleHandler::getModulePath($module); - if(!$class_path) return; - - // Check if module.xml exists in the path. Return if not exist - $xml_file = sprintf("%sconf/module.xml", $class_path); - if(!file_exists($xml_file)) return; - - // Check if cached file exists - $cache_file = sprintf(_XE_PATH_ . "files/cache/module_info/%s.%s.%s.php", $module, Context::getLangType(), __XE_VERSION__); - - // Update if no cache file exists or it is older than xml file - if(!file_exists($cache_file) || filemtime($cache_file) < filemtime($xml_file) || $re_cache) + // Check the path and XML file name. + $module_path = ModuleHandler::getModulePath($module); + if (!$module_path) return; + $xml_file = $module_path . 'conf/module.xml'; + if (!file_exists($xml_file)) return; + + // Load the XML file and cache the definition. + $mtim1 = filemtime($xml_file); + $cache_key = sprintf('site_and_module:module_info_xml:%s:%d', $module, $mtime); + $info = Rhymix\Framework\Cache::get($cache_key); + if($info === null) { - $info = new stdClass(); - $buff = array(); // /< Set buff variable to use in the cache file - $buff[] = 'default_index_act = \'%s\';'; - $buff['setup_index_act'] = '$info->setup_index_act=\'%s\';'; - $buff['simple_setup_index_act'] = '$info->simple_setup_index_act=\'%s\';'; - $buff['admin_index_act'] = '$info->admin_index_act = \'%s\';'; - - $xml_obj = XmlParser::loadXmlFile($xml_file); // /< Read xml file and convert it to xml object - - if(!countobj($xml_obj->module)) return; // /< Error occurs if module tag doesn't included in the xml - - $grants = $xml_obj->module->grants->grant; // /< Permission information - $permissions = $xml_obj->module->permissions->permission; // /< Acting permission - $menus = $xml_obj->module->menus->menu; - $actions = $xml_obj->module->actions->action; // /< Action list (required) - - $default_index = $admin_index = ''; - - // Arrange permission information - if($grants) - { - if(is_array($grants)) $grant_list = $grants; - else $grant_list[] = $grants; - - $info->grant = new stdClass(); - $buff[] = '$info->grant = new stdClass;'; - foreach($grant_list as $grant) - { - $name = $grant->attrs->name; - $default = $grant->attrs->default?$grant->attrs->default:'guest'; - $title = $grant->title->body; - - $info->grant->{$name} = new stdClass(); - $info->grant->{$name}->title = $title; - $info->grant->{$name}->default = $default; - - $buff[] = sprintf('$info->grant->%s = new stdClass;', $name); - $buff[] = sprintf('$info->grant->%s->title=\'%s\';', $name, $title); - $buff[] = sprintf('$info->grant->%s->default=\'%s\';', $name, $default); - } - } - // Permissions to grant - if($permissions) - { - if(is_array($permissions)) $permission_list = $permissions; - else $permission_list[] = $permissions; - - $buff[] = '$info->permission = new stdClass;'; - $buff[] = '$info->permission_check = new stdClass;'; - - $info->permission = new stdClass; - $info->permission_check = new stdClass; - - foreach($permission_list as $permission) - { - $action = $permission->attrs->action; - $target = $permission->attrs->target; - - $info->permission->$action = $target; - - $buff[] = sprintf('$info->permission->%s = \'%s\';', $action, $target); - - $info->permission_check->$action = new stdClass; - $info->permission_check->$action->key = $permission->attrs->check_var ?: ''; - $info->permission_check->$action->type = $permission->attrs->check_type ?: ''; - - $buff[] = sprintf('$info->permission_check->%s = new stdClass;', $action); - $buff[] = sprintf('$info->permission_check->%s->key = \'%s\';', $action, $info->permission_check->$action->key); - $buff[] = sprintf('$info->permission_check->%s->type = \'%s\';', $action, $info->permission_check->$action->type); - } - } - // for admin menus - if($menus) - { - if(is_array($menus)) $menu_list = $menus; - else $menu_list[] = $menus; - - $buff[] = '$info->menu = new stdClass;'; - $info->menu = new stdClass(); - - foreach($menu_list as $menu) - { - $menu_name = $menu->attrs->name; - $menu_title = is_array($menu->title) ? $menu->title[0]->body : $menu->title->body; - $menu_type = $menu->attrs->type; - - $info->menu->{$menu_name} = new stdClass(); - $info->menu->{$menu_name}->title = $menu_title; - $info->menu->{$menu_name}->acts = array(); - $info->menu->{$menu_name}->type = $menu_type; - - $buff[] = sprintf('$info->menu->%s = new stdClass;', $menu_name); - $buff[] = sprintf('$info->menu->%s->title=\'%s\';', $menu_name, $menu_title); - $buff[] = sprintf('$info->menu->%s->type=\'%s\';', $menu_name, $menu_type); - } - } - - // actions - if($actions) - { - if(is_array($actions)) $action_list = $actions; - else $action_list[] = $actions; - - if(!isset($info->permission)) - { - $buff[] = '$info->permission = new stdClass;'; - $buff[] = '$info->permission_check = new stdClass;'; - - $info->permission = new stdClass; - $info->permission_check = new stdClass; - } - - $buff[] = '$info->action = new stdClass;'; - $info->action = new stdClass(); - - foreach($action_list as $action) - { - $name = $action->attrs->name; - - // - if($action->attrs->permission) - { - $info->permission->$name = $action->attrs->permission; - - $buff[] = sprintf('$info->permission->%s = \'%s\';', $name, $info->permission->$name); - - $info->permission_check->$name = new stdClass; - $info->permission_check->$name->key = $action->attrs->check_var ?: ''; - $info->permission_check->$name->type = $action->attrs->check_type ?: ''; - - $buff[] = sprintf('$info->permission_check->%s = new stdClass;', $name); - $buff[] = sprintf('$info->permission_check->%s->key = \'%s\';', $name, $info->permission_check->$name->key); - $buff[] = sprintf('$info->permission_check->%s->type = \'%s\';', $name, $info->permission_check->$name->type); - } - - $type = $action->attrs->type; - $grant = $action->attrs->grant?$action->attrs->grant:'guest'; - $standalone = $action->attrs->standalone=='false'?'false':'true'; - $ruleset = $action->attrs->ruleset?$action->attrs->ruleset:''; - $method = $action->attrs->method?$action->attrs->method:''; - $check_csrf = $action->attrs->check_csrf=='false'?'false':'true'; - $meta_noindex = $action->attrs->{'meta-noindex'} === 'true' ? 'true' : 'false'; - - $index = $action->attrs->index; - $admin_index = $action->attrs->admin_index; - $setup_index = $action->attrs->setup_index; - $simple_setup_index = $action->attrs->simple_setup_index; - $menu_index = $action->attrs->menu_index; - - $info->action->{$name} = new stdClass(); - $info->action->{$name}->type = $type; - $info->action->{$name}->grant = $grant; - $info->action->{$name}->standalone = $standalone; - $info->action->{$name}->ruleset = $ruleset; - $info->action->{$name}->method = $method; - $info->action->{$name}->check_csrf = $check_csrf; - $info->action->{$name}->meta_noindex = $meta_noindex; - if($action->attrs->menu_name) - { - $info->menu->{$action->attrs->menu_name} = new stdClass(); - if($menu_index == 'true') - { - $info->menu->{$action->attrs->menu_name}->index = $name; - $buff[] = sprintf('$info->menu->%s->index=\'%s\';', $action->attrs->menu_name, $name); - } - if(is_array($info->menu->{$action->attrs->menu_name}->acts)) - { - $info->menu->{$action->attrs->menu_name}->acts[] = $name; - } - - $buff[] = sprintf('$info->menu->%s->acts[]=\'%s\';', $action->attrs->menu_name, $name); - $i++; - } - - $buff[] = sprintf('$info->action->%s = new stdClass;', $name); - $buff[] = sprintf('$info->action->%s->type=\'%s\';', $name, $type); - $buff[] = sprintf('$info->action->%s->grant=\'%s\';', $name, $grant); - $buff[] = sprintf('$info->action->%s->standalone=\'%s\';', $name, $standalone); - $buff[] = sprintf('$info->action->%s->ruleset=\'%s\';', $name, $ruleset); - $buff[] = sprintf('$info->action->%s->method=\'%s\';', $name, $method); - $buff[] = sprintf('$info->action->%s->check_csrf=\'%s\';', $name, $check_csrf); - $buff[] = sprintf('$info->action->%s->meta_noindex=\'%s\';', $name, $meta_noindex); - - if($index=='true') - { - $default_index_act = $name; - $info->default_index_act = $name; - } - if($admin_index=='true') - { - $admin_index_act = $name; - $info->admin_index_act = $name; - } - if($setup_index=='true') - { - $setup_index_act = $name; - $info->setup_index_act = $name; - } - if($simple_setup_index=='true') - { - $simple_setup_index_act = $name; - $info->simple_setup_index_act = $name; - } - } - } - $buff['default_index_act'] = sprintf($buff['default_index_act'], $default_index_act); - $buff['setup_index_act'] = sprintf($buff['setup_index_act'], $setup_index_act); - $buff['simple_setup_index_act'] = sprintf($buff['simple_setup_index_act'], $simple_setup_index_act); - $buff['admin_index_act'] = sprintf($buff['admin_index_act'], $admin_index_act); - - $buff[] = 'return $info;'; - - $buff = implode(PHP_EOL, $buff); - - FileHandler::writeFile($cache_file, $buff); - - return $info; + $info = Rhymix\Framework\Parsers\ModuleActionParser::loadXML($xml_file); + Rhymix\Framework\Cache::set($cache_key, $info); } - - if(file_exists($cache_file)) return include($cache_file); + + return $info; } /**