From a1f452fa83aa8dccdeaa4a44054e579ea294f4e9 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 15 May 2025 20:11:49 +0900 Subject: [PATCH 01/69] Fix missing extra vars when document cache is cleared in the middle of a script #2553 --- modules/document/document.controller.php | 3 +++ modules/document/document.model.php | 15 ++++++--------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/document/document.controller.php b/modules/document/document.controller.php index 4d154679d..414def49c 100644 --- a/modules/document/document.controller.php +++ b/modules/document/document.controller.php @@ -1775,6 +1775,7 @@ class DocumentController extends Document $output = executeQuery('document.updateDocumentExtraVar', $obj); } + unset($GLOBALS['XE_EXTRA_KEYS'][$module_srl]); Rhymix\Framework\Cache::delete("site_and_module:module_document_extra_keys:$module_srl"); return $output; } @@ -1831,6 +1832,7 @@ class DocumentController extends Document $oDB->commit(); + unset($GLOBALS['XE_EXTRA_KEYS'][$module_srl]); Rhymix\Framework\Cache::delete("site_and_module:module_document_extra_keys:$module_srl"); return new BaseObject(); } @@ -3708,6 +3710,7 @@ Content; if ($type === 'all' || $type === 'extra_vars') { unset($GLOBALS['XE_EXTRA_VARS'][$document_srl]); + unset($GLOBALS['XE_EXTRA_CHK'][$document_srl]); unset($GLOBALS['RX_DOCUMENT_LANG'][$document_srl]); } } diff --git a/modules/document/document.model.php b/modules/document/document.model.php index ea6cd90c3..9b15bcd97 100644 --- a/modules/document/document.model.php +++ b/modules/document/document.model.php @@ -55,19 +55,16 @@ class DocumentModel extends Document return; } - static $checked = array(); - static $module_extra_keys = array(); - // check documents $document_srls = array(); foreach($_document_list as $document_srl => $oDocument) { - if(isset($checked[$document_srl]) || !($oDocument instanceof documentItem) || !$oDocument->isExists()) + if(isset($GLOBALS['XE_EXTRA_CHK'][$document_srl]) || !($oDocument instanceof documentItem) || !$oDocument->isExists()) { continue; } - $checked[$document_srl] = true; + $GLOBALS['XE_EXTRA_CHK'][$document_srl] = true; $document_srls[] = $document_srl; } @@ -102,16 +99,16 @@ class DocumentModel extends Document if(!isset($GLOBALS['XE_EXTRA_VARS'][$document_srl])) { // get extra keys of the module - if(!isset($module_extra_keys[$module_srl])) + if(!isset($GLOBALS['XE_EXTRA_KEYS'][$module_srl])) { - $module_extra_keys[$module_srl] = self::getExtraKeys($module_srl); + $GLOBALS['XE_EXTRA_KEYS'][$module_srl] = self::getExtraKeys($module_srl); } // set extra variables of the document - if($module_extra_keys[$module_srl]) + if(!empty($GLOBALS['XE_EXTRA_KEYS'][$module_srl])) { $document_extra_vars = array(); - foreach($module_extra_keys[$module_srl] as $idx => $key) + foreach($GLOBALS['XE_EXTRA_KEYS'][$module_srl] as $idx => $key) { $document_extra_vars[$idx] = clone($key); From db72b670d824b6b9fbcdb4d6182794fa91fb7296 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sat, 17 May 2025 12:44:04 +0900 Subject: [PATCH 02/69] Replace XE XML parser with new implementation based on SimpleXML --- classes/xml/XmlParser.class.php | 238 +++-------------------- common/framework/parsers/XEXMLParser.php | 105 ++++++++++ 2 files changed, 127 insertions(+), 216 deletions(-) create mode 100644 common/framework/parsers/XEXMLParser.php diff --git a/classes/xml/XmlParser.class.php b/classes/xml/XmlParser.class.php index d08bdfd75..b4f65f102 100644 --- a/classes/xml/XmlParser.class.php +++ b/classes/xml/XmlParser.class.php @@ -1,240 +1,46 @@ { - * This class may drops unsupported xml lanuage attributes when multiple language attributes are given. - * For example, if 'xml:lang='ko, en, ch, jp..' is given in a xml file, only ko will be left ignoring all other language - * attributes when kor is only supported language. It seems to work fine now but we did not scrutinze any potential side effects, - * } + * XML Parser class from XE * - * @author NAVER (developers@xpressengine.com) - * @package /classes/xml - * @version 0.1 + * Renamed because of conflict with built-in XMLParser class in PHP 8+ + * + * @deprecated */ class XeXmlParser { - /** - * Xml parser - * @var resource + * Load an XML file. + * + * @deprecated + * @param string $filename + * @return ?object */ - var $oParser = NULL; - - /** - * Input xml - * @var string - */ - var $input = NULL; - - /** - * Output object in array - * @var array - */ - var $output = array(); - - /** - * The default language type - * @var string - */ - var $lang = "en"; - - /** - * Load a xml file specified by a filename and parse it to Return the resultant data object - * @param string $filename a file path of file - * @return object|null Returns a data object containing data extracted from a xml file or NULL if a specified file does not exist - */ - function loadXmlFile($filename) + public static function loadXmlFile($filename): ?object { - if(!file_exists($filename)) + $filename = strval($filename); + if (file_exists($filename)) { - return; - } - $buff = FileHandler::readFile($filename); - - $oXmlParser = new self(); - return $oXmlParser->parse($buff); - } - - /** - * Parse xml data to extract values from it and construct data object - * @param string $input a data buffer containing xml data - * @param mixed $arg1 ??? - * @param mixed $arg2 ??? - * @return object|null Returns a resultant data object or NULL in case of error - */ - function parse($input = '', $arg1 = NULL, $arg2 = NULL) - { - // Save the compile starting time for debugging - $start = microtime(true); - - $this->lang = Context::getLangType(); - - $this->input = $input ? $input : $GLOBALS['HTTP_RAW_POST_DATA']; - $this->input = str_replace(array('', ''), array('', ''), $this->input); - - // extracts a supported language - preg_match_all("/xml:lang=\"([^\"].+)\"/i", $this->input, $matches); - - // extracts the supported lanuage when xml:lang is used - if(count($matches[1]) && $supported_lang = array_unique($matches[1])) - { - $tmpLangList = array_flip($supported_lang); - // if lang of the first log-in user doesn't exist, apply en by default if exists. Otherwise apply the first lang. - if(!isset($tmpLangList[$this->lang])) - { - if(isset($tmpLangList['en'])) - { - $this->lang = 'en'; - } - else - { - $this->lang = array_shift($supported_lang); - } - } - // uncheck the language if no specific language is set. + return Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($filename); } else { - $this->lang = ''; - } - - $this->oParser = xml_parser_create('UTF-8'); - - //xml_set_object($this->oParser, $this); - xml_set_element_handler($this->oParser, [$this, "_tagOpen"], [$this, "_tagClosed"]); - xml_set_character_data_handler($this->oParser, [$this, "_tagBody"]); - - xml_parse($this->oParser, $this->input); - xml_parser_free($this->oParser); - - if(!count($this->output)) - { - return; - } - - $output = array_shift($this->output); - // Save compile starting time for debugging - if (!isset($GLOBALS['__xmlparse_elapsed__'])) - { - $GLOBALS['__xmlparse_elapsed__'] = 0; - } - $GLOBALS['__xmlparse_elapsed__'] += microtime(true) - $start; - - return $output; - } - - /** - * Start element handler. - * @param resource $parse an instance of parser - * @param string $node_name a name of node - * @param array $attrs attributes to be set - * @return array - */ - function _tagOpen($parser, $node_name, $attrs) - { - $obj = new Xml_Node_(); - $obj->node_name = strtolower($node_name); - $obj->attrs = $this->_arrToAttrsObj($attrs); - - $this->output[] = $obj; - } - - /** - * Character data handler - * Variable in the last element of this->output - * @param resource $parse an instance of parser - * @param string $body a data to be added - * @return void - */ - function _tagBody($parser, $body) - { - //if(!trim($body)) return; - $this->output[count($this->output) - 1]->body .= $body; - } - - /** - * End element handler - * @param resource $parse an instance of parser - * @param string $node_name name of xml node - * @return void - */ - function _tagClosed($parser, $node_name) - { - $node_name = strtolower($node_name); - $cur_obj = array_pop($this->output); - $parent_obj = &$this->output[count($this->output) - 1]; - if($this->lang && $cur_obj->attrs->{'xml:lang'} && $cur_obj->attrs->{'xml:lang'} != $this->lang) - { - return; - } - if($this->lang && ($parent_obj->{$node_name}->attrs->{'xml:lang'} ?? null) && $parent_obj->{$node_name}->attrs->{'xml:lang'} != $this->lang) - { - return; - } - - if(isset($parent_obj->{$node_name})) - { - $tmp_obj = $parent_obj->{$node_name}; - if(is_array($tmp_obj)) - { - $parent_obj->{$node_name}[] = $cur_obj; - } - else - { - $parent_obj->{$node_name} = array($tmp_obj, $cur_obj); - } - } - else - { - if(!is_object($parent_obj)) - { - $parent_obj = (object) $parent_obj; - } - - $parent_obj->{$node_name} = $cur_obj; + return null; } } /** - * Method to transfer values in an array to a data object - * @param array $arr data array - * @return Xml_Node_ object + * Load an XML string. + * + * @deprecated + * @param string $$input + * @return ?object */ - function _arrToAttrsObj($arr) + function parse($input = ''): ?object { - $output = new Xml_Node_(); - foreach($arr as $key => $val) - { - $key = strtolower($key); - $output->{$key} = $val; - } - return $output; + $input = strval($input !== '' ? $input : $GLOBALS['HTTP_RAW_POST_DATA']); + return Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($input); } - } /** diff --git a/common/framework/parsers/XEXMLParser.php b/common/framework/parsers/XEXMLParser.php new file mode 100644 index 000000000..a87ba179a --- /dev/null +++ b/common/framework/parsers/XEXMLParser.php @@ -0,0 +1,105 @@ +getName(); + $result->$root_name = self::_recursiveConvert($xml, $lang); + return $result; + } + + /** + * Convert an XML node recursively. + * + * @param \SimpleXMLElement $element + * @param string $lang + * @return object + */ + protected static function _recursiveConvert(\SimpleXMLElement $element, string $lang): \stdClass + { + // Create the basic structure of the node. + $node = new \stdClass; + $node->node_name = $element->getName(); + $node->attrs = new \stdClass; + $node->body = trim($element->__toString()); + + // Add attributes. + $attrs = $element->attributes(); + foreach ($attrs as $key => $val) + { + $node->attrs->{$key} = trim($val); + } + $attrs = $element->attributes('xml', true); + foreach ($attrs as $key => $val) + { + $node->attrs->{"xml:$key"} = trim($val); + } + + // Recursively process child elements. + foreach ($element->children() as $child) + { + // Skip children that do not match the language. + $attrs = $child->attributes('xml', true); + if (isset($attrs['lang']) && strval($attrs['lang']) !== $lang) + { + continue; + } + + $child_name = $child->getName(); + $child_node = self::_recursiveConvert($child, $lang); + if (!isset($node->$child_name)) + { + $node->$child_name = $child_node; + } + elseif (is_array($node->$child_name)) + { + $node->$child_name[] = $child_node; + } + else + { + $node->$child_name = [$node->$child_name, $child_node]; + } + } + + return $node; + } +} From 52f106968a42210b1456e6b65ab7188ddd27fb90 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sat, 17 May 2025 12:54:47 +0900 Subject: [PATCH 03/69] Add unit test for XEXMLParser --- tests/_data/xml/xecompat.xml | 25 +++++++++++++++++ .../{xmlrpc/request.xml => xml/xmlrpc.xml} | 0 .../framework/parsers/XeXmlParserTest.php | 27 +++++++++++++++++++ .../framework/parsers/XmlrpcParserTest.php | 2 +- 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/_data/xml/xecompat.xml rename tests/_data/{xmlrpc/request.xml => xml/xmlrpc.xml} (100%) create mode 100644 tests/unit/framework/parsers/XeXmlParserTest.php diff --git a/tests/_data/xml/xecompat.xml b/tests/_data/xml/xecompat.xml new file mode 100644 index 000000000..85d6479bf --- /dev/null +++ b/tests/_data/xml/xecompat.xml @@ -0,0 +1,25 @@ + + + 기본 레이아웃 + Default Layout + + 라이믹스 + Rhymix + + + + 로고 이미지 + Logo Image + + + 웹 폰트 + Web Font + + Noto Sans + + + Pretendard + + + + diff --git a/tests/_data/xmlrpc/request.xml b/tests/_data/xml/xmlrpc.xml similarity index 100% rename from tests/_data/xmlrpc/request.xml rename to tests/_data/xml/xmlrpc.xml diff --git a/tests/unit/framework/parsers/XeXmlParserTest.php b/tests/unit/framework/parsers/XeXmlParserTest.php new file mode 100644 index 000000000..8ef9a9345 --- /dev/null +++ b/tests/unit/framework/parsers/XeXmlParserTest.php @@ -0,0 +1,27 @@ +assertEquals('Default Layout', $output->layout->title->body); + $this->assertEquals('Rhymix', $output->layout->author->name->body); + $this->assertEquals('https://rhymix.org/', $output->layout->author->attrs->link); + $this->assertEquals('en', $output->layout->author->name->attrs->{'xml:lang'}); + + $this->assertEquals('logo_image', $output->layout->extra_vars->var[0]->attrs->name); + $this->assertEquals('web_font', $output->layout->extra_vars->var[1]->attrs->name); + $this->assertEquals('Noto Sans', $output->layout->extra_vars->var[1]->options[0]->attrs->value); + $this->assertEquals('Pretendard', $output->layout->extra_vars->var[1]->options[1]->title->body); + + $output = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($xml, 'ko'); + + $this->assertEquals('기본 레이아웃', $output->layout->title->body); + $this->assertEquals('라이믹스', $output->layout->author->name->body); + $this->assertEquals('웹 폰트', $output->layout->extra_vars->var[1]->title->body); + $this->assertEquals('Noto Sans', $output->layout->extra_vars->var[1]->options[0]->attrs->value); + } +} diff --git a/tests/unit/framework/parsers/XmlrpcParserTest.php b/tests/unit/framework/parsers/XmlrpcParserTest.php index e6dd19c6b..3771cb497 100644 --- a/tests/unit/framework/parsers/XmlrpcParserTest.php +++ b/tests/unit/framework/parsers/XmlrpcParserTest.php @@ -4,7 +4,7 @@ class XmlrpcParserTest extends \Codeception\Test\Unit { public function testParse() { - $xml = file_get_contents(\RX_BASEDIR . 'tests/_data/xmlrpc/request.xml'); + $xml = file_get_contents(\RX_BASEDIR . 'tests/_data/xml/xmlrpc.xml'); $params = Rhymix\Framework\Parsers\XMLRPCParser::parse($xml); $this->assertTrue(is_array($params)); $this->assertEquals('board', $params['module']); From bfa8ea5ddcd617ebb601c088017f9112a974387f Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sat, 17 May 2025 12:58:31 +0900 Subject: [PATCH 04/69] Fix undefined property access in Validator class --- classes/validator/Validator.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/validator/Validator.class.php b/classes/validator/Validator.class.php index 531872b92..632b35b79 100644 --- a/classes/validator/Validator.class.php +++ b/classes/validator/Validator.class.php @@ -146,7 +146,7 @@ class Validator continue; } - $message = $rule->message ? $rule->message->body : NULL; + $message = isset($rule->message) ? $rule->message->body : NULL; $rule = (array) $rule->attrs; $rule['message'] = $message; $name = $rule['name']; @@ -183,7 +183,7 @@ class Validator continue; } - $title = $field->title ? $field->title->body : NULL; + $title = isset($field->title) ? $field->title->body : NULL; $filter = (array) $field->attrs; $filter['title'] = $title; From e0ba5aa5b6bdd541105b208a6de2048eeb2e78c3 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sat, 17 May 2025 13:02:29 +0900 Subject: [PATCH 05/69] Prevent undefined property errors in XEXMLParser use cases --- common/framework/parsers/XEXMLParser.php | 28 +++++++++++++------ .../framework/parsers/XeXmlParserTest.php | 3 ++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/common/framework/parsers/XEXMLParser.php b/common/framework/parsers/XEXMLParser.php index a87ba179a..c3f01ec5f 100644 --- a/common/framework/parsers/XEXMLParser.php +++ b/common/framework/parsers/XEXMLParser.php @@ -12,9 +12,9 @@ class XEXMLParser * * @param string $filename * @param string $lang - * @return ?object + * @return ?self */ - public static function loadXMLFile(string $filename, string $lang = ''): ?object + public static function loadXMLFile(string $filename, string $lang = ''): ?self { $content = file_get_contents($filename); return self::loadXMLString($content, $lang); @@ -25,9 +25,9 @@ class XEXMLParser * * @param string $filename * @param string $lang - * @return ?object + * @return ?self */ - public static function loadXMLString(string $content, string $lang = ''): ?object + public static function loadXMLString(string $content, string $lang = ''): ?self { // Apply transformations identical to XE's XML parser. $content = str_replace([chr(1), chr(2)], ['', ''], $content); @@ -41,7 +41,7 @@ class XEXMLParser $lang = $lang ?: (\Context::getLangType() ?: 'en'); // Create the result object. - $result = new \stdClass; + $result = new self; $root_name = $xml->getName(); $result->$root_name = self::_recursiveConvert($xml, $lang); return $result; @@ -52,14 +52,14 @@ class XEXMLParser * * @param \SimpleXMLElement $element * @param string $lang - * @return object + * @return self */ - protected static function _recursiveConvert(\SimpleXMLElement $element, string $lang): \stdClass + protected static function _recursiveConvert(\SimpleXMLElement $element, string $lang): self { // Create the basic structure of the node. - $node = new \stdClass; + $node = new self; $node->node_name = $element->getName(); - $node->attrs = new \stdClass; + $node->attrs = new self; $node->body = trim($element->__toString()); // Add attributes. @@ -102,4 +102,14 @@ class XEXMLParser return $node; } + + /** + * Hack to prevent undefined property errors. + * + * @param string $name + */ + public function __get($name) + { + return isset($this->$name) ? $this->$name : null; + } } diff --git a/tests/unit/framework/parsers/XeXmlParserTest.php b/tests/unit/framework/parsers/XeXmlParserTest.php index 8ef9a9345..c6ae8f215 100644 --- a/tests/unit/framework/parsers/XeXmlParserTest.php +++ b/tests/unit/framework/parsers/XeXmlParserTest.php @@ -23,5 +23,8 @@ class XeXmlParserTest extends \Codeception\Test\Unit $this->assertEquals('라이믹스', $output->layout->author->name->body); $this->assertEquals('웹 폰트', $output->layout->extra_vars->var[1]->title->body); $this->assertEquals('Noto Sans', $output->layout->extra_vars->var[1]->options[0]->attrs->value); + + $this->assertInstanceOf(\Rhymix\Framework\Parsers\XEXMLParser::class, $output); + $this->assertNull($output->layout->attrs->foo); } } From 8c87d9ee1defa99764807bb7a7808c51f79f9a98 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sat, 17 May 2025 13:06:54 +0900 Subject: [PATCH 06/69] Allow dynamic properties in XEXMLParser --- common/framework/parsers/XEXMLParser.php | 1 + 1 file changed, 1 insertion(+) diff --git a/common/framework/parsers/XEXMLParser.php b/common/framework/parsers/XEXMLParser.php index c3f01ec5f..2f944a995 100644 --- a/common/framework/parsers/XEXMLParser.php +++ b/common/framework/parsers/XEXMLParser.php @@ -5,6 +5,7 @@ namespace Rhymix\Framework\Parsers; /** * Generic XML parser that produces output identical to XE's XML parser. */ +#[\AllowDynamicProperties] class XEXMLParser { /** From addf4d9972707853e678ecb6e16b380549111330 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sat, 17 May 2025 23:46:58 +0900 Subject: [PATCH 07/69] Fix incorrect type hints --- common/framework/parsers/DBQueryParser.php | 4 ++-- common/framework/parsers/DBTableParser.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/framework/parsers/DBQueryParser.php b/common/framework/parsers/DBQueryParser.php index bac0940ad..674648682 100644 --- a/common/framework/parsers/DBQueryParser.php +++ b/common/framework/parsers/DBQueryParser.php @@ -31,7 +31,7 @@ class DBQueryParser extends BaseParser /** * Parse a query. * - * @param SimpleXMLElement $xml + * @param \SimpleXMLElement $xml * @param string $name * @return object */ @@ -248,7 +248,7 @@ class DBQueryParser extends BaseParser /** * Parse conditions. * - * @param SimpleXMLElement $parent + * @param \SimpleXMLElement $parent * @return array */ protected static function _parseConditions(\SimpleXMLElement $parent): array diff --git a/common/framework/parsers/DBTableParser.php b/common/framework/parsers/DBTableParser.php index 8ba82b924..b2245d668 100644 --- a/common/framework/parsers/DBTableParser.php +++ b/common/framework/parsers/DBTableParser.php @@ -33,7 +33,7 @@ class DBTableParser extends BaseParser * @param string $content * @return ?object */ - public static function loadXML(string $filename = '', string $content = ''): object + public static function loadXML(string $filename = '', string $content = ''): ?object { // Load the XML content. if ($content) From a3d682a2947658679ae1e84027236012931af912 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sun, 18 May 2025 21:42:36 +0900 Subject: [PATCH 08/69] Rewrite addon info.xml parser and support default values --- common/framework/parsers/AddonInfoParser.php | 95 ++++++++ common/framework/parsers/BaseParser.php | 14 +- modules/addon/addon.admin.controller.php | 19 +- modules/addon/addon.admin.model.php | 238 +++---------------- 4 files changed, 146 insertions(+), 220 deletions(-) create mode 100644 common/framework/parsers/AddonInfoParser.php diff --git a/common/framework/parsers/AddonInfoParser.php b/common/framework/parsers/AddonInfoParser.php new file mode 100644 index 000000000..3ea9c820f --- /dev/null +++ b/common/framework/parsers/AddonInfoParser.php @@ -0,0 +1,95 @@ +addon_name = $addon_name; + + // Get the XML schema version. + $version = strval($xml['version']) ?: '0.1'; + + // Parse version 0.2 + if ($version === '0.2') + { + $info->title = self::_getChildrenByLang($xml, 'title', $lang); + $info->description = self::_getChildrenByLang($xml, 'description', $lang); + $info->version = trim($xml->version); + $info->date = ($xml->date === 'RX_CORE') ? '' : date('Ymd', strtotime($xml->date . 'T12:00:00Z')); + $info->homepage = trim($xml->homepage); + $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::_getChildrenByLang($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::_getChildrenByLang($xml, 'title', $lang); + $info->description = self::_getChildrenByLang($xml->author, 'description', $lang); + $info->version = trim($xml['version'] ?? ''); + $info->date = date('Ymd', strtotime($xml->author['date'] . 'T12:00:00Z')); + $info->homepage = trim($xml->homepage); + $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::_getChildrenByLang($author, 'name', $lang); + $author_info->email_address = trim($author['email_address']); + $author_info->homepage = trim($author['link'] ?? ''); + $info->author[] = $author_info; + } + } + + // Get extra_vars. + if ($xml->extra_vars) + { + $info->extra_vars = get_object_vars(self::_getExtraVars($xml->extra_vars, $lang)); + } + + // Prepare additional fields that will be filled in later. + $info->is_enabled = (object)['pc' => false, 'mobile' => false]; + $info->xe_run_method = 'run_selected'; + $info->mid_list = []; + + // Return the complete result. + return $info; + } +} diff --git a/common/framework/parsers/BaseParser.php b/common/framework/parsers/BaseParser.php index 1677aa67b..0c1fb111b 100644 --- a/common/framework/parsers/BaseParser.php +++ b/common/framework/parsers/BaseParser.php @@ -10,7 +10,7 @@ abstract class BaseParser /** * Get all attributes of an element as an associative array. * - * @param SimpleXMLElement $element + * @param \SimpleXMLElement $element * @param bool $normalize * @return array */ @@ -31,7 +31,7 @@ abstract class BaseParser /** * Get the string value of an XML attribute after normalizing its name. * - * @param SimpleXMLElement $element + * @param \SimpleXMLElement $element * @param string $name * @return string */ @@ -55,7 +55,7 @@ abstract class BaseParser * A value that is identical to the name of the attribute will be treated as true. * Other values will be passed to toBool() for evaluation. * - * @param SimpleXMLElement $element + * @param \SimpleXMLElement $element * @param string $name * @return bool */ @@ -77,7 +77,7 @@ abstract class BaseParser /** * Get the contents of child elements that match a language. * - * @param SimpleXMLElement $parent + * @param \SimpleXMLElement $parent * @param string $tag_name * @param string $lang * @return string @@ -107,7 +107,7 @@ abstract class BaseParser /** * Parse extra_vars. * - * @param SimpleXMLElement $extra_vars + * @param \SimpleXMLElement $extra_vars * @param string $lang * @return object */ @@ -132,6 +132,10 @@ abstract class BaseParser $item->title = self::_getChildrenByLang($var, 'title', $lang); $item->description = str_replace('\\n', "\n", self::_getChildrenByLang($var, 'description', $lang)); $item->default = trim($var['default']) ?: null; + if (!isset($item->default)) + { + $item->default = self::_getChildrenByLang($var, 'default', $lang); + } $item->value = null; if ($var->options) { diff --git a/modules/addon/addon.admin.controller.php b/modules/addon/addon.admin.controller.php index 7fc7b505b..e6cdb3b2b 100644 --- a/modules/addon/addon.admin.controller.php +++ b/modules/addon/addon.admin.controller.php @@ -197,16 +197,19 @@ class addonAdminController extends addonController */ function procAddonAdminSetupAddon() { - $args = Context::getRequestVars(); - $module = $args->module; - $addon_name = $args->addon_name; - unset($args->module); - unset($args->act); - unset($args->addon_name); - unset($args->body); - unset($args->error_return_url); + $vars = Context::getRequestVars(); + $module = $vars->module; + $addon_name = $vars->addon_name; + $args = new stdClass(); $site_module_info = Context::get('site_module_info'); + $addon_info = AddonAdminModel::getInstance()->getAddonInfoXml($addon_name, $site_module_info->site_srl, 'site'); + foreach ($addon_info->extra_vars as $key => $val) + { + $args->{$key} = $vars->{$key} ?? ''; + } + $args->xe_run_method = $vars->xe_run_method ?? ''; + $args->mid_list = $vars->mid_list ?? []; $output = $this->doSetup($addon_name, $args, $site_module_info->site_srl, 'site'); if(!$output->toBool()) diff --git a/modules/addon/addon.admin.model.php b/modules/addon/addon.admin.model.php index a5bacaa23..61ba824ea 100644 --- a/modules/addon/addon.admin.model.php +++ b/modules/addon/addon.admin.model.php @@ -162,18 +162,14 @@ class addonAdminModel extends addon return; } - // Read the xml file for module skin information + // Read the xml file for addon information $xml_file = sprintf("%sconf/info.xml", FileHandler::getRealpath($addon_path)); - if(!file_exists($xml_file)) + if (!file_exists($xml_file)) { return; } - - $oXmlParser = new XeXmlParser(); - $tmp_xml_obj = $oXmlParser->loadXmlFile($xml_file); - $xml_obj = $tmp_xml_obj->addon; - - if(!$xml_obj) + $addon_info = Rhymix\Framework\Parsers\AddonInfoParser::loadXML($xml_file, $addon); + if (!$addon_info) { return; } @@ -190,224 +186,52 @@ class addonAdminModel extends addon $db_args->site_srl = $site_srl; $output = executeQuery('addon.getSiteAddonInfo', $db_args); } - $extra_vals = unserialize($output->data->extra_vars); - $addon_info = new stdClass(); - if($extra_vals->mid_list) + // Add run settings + $extra_vals = isset($output->data->extra_vars) ? unserialize($output->data->extra_vars) : new stdClass; + if (!empty($extra_vals->mid_list)) { $addon_info->mid_list = $extra_vals->mid_list; } - else - { - $addon_info->mid_list = array(); - } - - if($extra_vals->xe_run_method) + if (!empty($extra_vals->xe_run_method)) { $addon_info->xe_run_method = $extra_vals->xe_run_method; } - - // Add information - if($xml_obj->version && $xml_obj->attrs->version == '0.2') + if (isset($output->data) && $output->data->is_used === 'Y') { - // addon format v0.2 - if ($xml_obj->date->body === 'RX_CORE') + $addon_info->is_enabled->pc = true; + } + if (isset($output->data) && $output->data->is_used_m === 'Y') + { + $addon_info->is_enabled->mobile = true; + } + + // Add current settings + foreach ($addon_info->extra_vars ?? [] as $key => $val) + { + if (isset($extra_vals->{$key})) { - $addon_info->date = ''; + if (is_string($extra_vals->{$key}) && str_contains($extra_vals->{$key}, '|@|')) + { + $val->value = explode('|@|', $extra_vals->{$key}); + } + else + { + $val->value = $extra_vals->{$key}; + } } else { - $date_obj = new stdClass(); - sscanf($xml_obj->date->body, '%d-%d-%d', $date_obj->y, $date_obj->m, $date_obj->d); - $addon_info->date = sprintf('%04d%02d%02d', $date_obj->y, $date_obj->m, $date_obj->d); + $val->value = $val->default; } - $addon_info->addon_name = $addon; - $addon_info->title = $xml_obj->title->body; - $addon_info->description = trim($xml_obj->description->body); - $addon_info->version = $xml_obj->version->body; - $addon_info->homepage = $xml_obj->link->body; - $addon_info->license = $xml_obj->license->body; - $addon_info->license_link = $xml_obj->license->attrs->link; - if(!is_array($xml_obj->author)) + if ($val->type === 'mid_list' && !is_array($val->value)) { - $author_list = array(); - $author_list[] = $xml_obj->author; - } - else - { - $author_list = $xml_obj->author; + $val->value = isset($val->value) ? [$val->value] : []; } - $addon_info->author = array(); - 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; - $addon_info->author[] = $author_obj; - } - - // Expand the variable order - if($xml_obj->extra_vars) - { - $extra_var_groups = $xml_obj->extra_vars->group; - if(!$extra_var_groups) - { - $extra_var_groups = $xml_obj->extra_vars; - } - if(!is_array($extra_var_groups)) - { - $extra_var_groups = array($extra_var_groups); - } - - foreach($extra_var_groups as $group) - { - $extra_vars = $group->var; - if(!is_array($group->var)) - { - $extra_vars = array($group->var); - } - - foreach($extra_vars as $key => $val) - { - if(!$val) - { - continue; - } - - $obj = new stdClass(); - if(!$val->attrs) - { - $val->attrs = new stdClass(); - } - if(!$val->attrs->type) - { - $val->attrs->type = 'text'; - } - - $obj->group = $group->title->body; - $obj->name = $val->attrs->name; - $obj->title = $val->title->body; - $obj->type = $val->attrs->type; - $obj->description = $val->description->body; - if($obj->name) - { - $obj->value = $extra_vals->{$obj->name}; - } - if(strpos($obj->value, '|@|') != FALSE) - { - $obj->value = explode('|@|', $obj->value); - } - if($obj->type == 'mid_list' && !is_array($obj->value)) - { - $obj->value = array($obj->value); - } - - // 'Select'type obtained from the option list. - if($val->options && !is_array($val->options)) - { - $val->options = array($val->options); - } - - for($i = 0, $c = countobj($val->options); $i < $c; $i++) - { - $obj->options[$i] = new stdClass(); - $obj->options[$i]->title = $val->options[$i]->title->body; - $obj->options[$i]->value = $val->options[$i]->attrs->value; - } - - $addon_info->extra_vars[] = $obj; - } - } - } } - else - { - // addon format 0.1 - $addon_info = new stdClass(); - $addon_info->addon_name = $addon; - $addon_info->title = $xml_obj->title->body; - $addon_info->description = trim($xml_obj->author->description->body); - $addon_info->version = $xml_obj->attrs->version; - $date_obj = new stdClass(); - sscanf($xml_obj->author->attrs->date, '%d. %d. %d', $date_obj->y, $date_obj->m, $date_obj->d); - $addon_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; - - $addon_info->author = array(); - $addon_info->author[] = $author_obj; - - if($xml_obj->extra_vars) - { - // Expand the variable order - $extra_var_groups = $xml_obj->extra_vars->group; - if(!$extra_var_groups) - { - $extra_var_groups = $xml_obj->extra_vars; - } - if(!is_array($extra_var_groups)) - { - $extra_var_groups = array($extra_var_groups); - } - foreach($extra_var_groups as $group) - { - $extra_vars = $group->var; - if(!is_array($group->var)) - { - $extra_vars = array($group->var); - } - - $addon_info->extra_vars = array(); - foreach($extra_vars as $key => $val) - { - if(!$val) - { - continue; - } - - $obj = new stdClass(); - - $obj->group = $group->title->body; - $obj->name = $val->attrs->name; - $obj->title = $val->title->body; - $obj->type = $val->type->body ? $val->type->body : 'text'; - $obj->description = $val->description->body; - if($obj->name) - { - $obj->value = $extra_vals->{$obj->name}; - } - if(strpos($obj->value, '|@|') != false) - { - $obj->value = explode('|@|', $obj->value); - } - if($obj->type == 'mid_list' && !is_array($obj->value)) - { - $obj->value = array($obj->value); - } - // 'Select'type obtained from the option list. - if($val->options && !is_array($val->options)) - { - $val->options = array($val->options); - } - - $obj->options = array(); - foreach ($val->options ?? [] as $i => $option) - { - $obj->options[$i]->title = $option->title->body; - $obj->options[$i]->value = $option->value->body; - } - $addon_info->extra_vars[] = $obj; - } - } - } - } return $addon_info; } From 170e183f8f561733c9146d6f77cc46398f01d2f3 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sun, 18 May 2025 21:59:37 +0900 Subject: [PATCH 09/69] Remove references to old XeXmlParser in most modules --- modules/admin/controllers/Dashboard.php | 3 +- .../importer/importer.admin.controller.php | 32 ++++++------------- modules/krzip/krzip.model.php | 3 +- modules/layout/layout.model.php | 16 ++++++---- modules/module/module.model.php | 3 +- 5 files changed, 22 insertions(+), 35 deletions(-) diff --git a/modules/admin/controllers/Dashboard.php b/modules/admin/controllers/Dashboard.php index d2b053298..365244a13 100644 --- a/modules/admin/controllers/Dashboard.php +++ b/modules/admin/controllers/Dashboard.php @@ -185,8 +185,7 @@ class Dashboard extends Base $params["act"] = "getResourceapiLastupdate"; $body = \XmlGenerater::generate($params); $buff = FileHandler::getRemoteResource($config->download_server, $body, 3, "POST", "application/xml"); - $xml_lUpdate = new \XeXmlParser(); - $lUpdateDoc = $xml_lUpdate->parse($buff); + $lUpdateDoc = \Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff); $updateDate = $lUpdateDoc->response->updatedate->body; if(!$updateDate) diff --git a/modules/importer/importer.admin.controller.php b/modules/importer/importer.admin.controller.php index 27d4e29d8..1c91c230e 100644 --- a/modules/importer/importer.admin.controller.php +++ b/modules/importer/importer.admin.controller.php @@ -18,11 +18,6 @@ class importerAdminController extends importer * @var int */ var $unit_count = 300; - /** - * Xml parser - * @var XmlParser - */ - var $oXmlParser = null; /** * Initialization @@ -346,8 +341,6 @@ class importerAdminController extends importer function importMember($key, $cur, $index_file) { if(!$cur) $cur = 0; - // Create the xmlParser object - $oXmlParser = new XeXmlParser(); // Create objects for importing member information $this->oMemberController = getController('member'); $this->oMemberModel = getModel('member'); @@ -368,7 +361,7 @@ class importerAdminController extends importer // Find a given location $target_file = trim(fgets($f, 1024)); // Load and parse the file - $xmlObj = $oXmlParser->loadXmlFile($target_file); + $xmlObj = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($target_file); FileHandler::removeFile($target_file); if(!$xmlObj) continue; // List Objects @@ -539,8 +532,6 @@ class importerAdminController extends importer function importMessage($key, $cur, $index_file) { if(!$cur) $cur = 0; - // Create the xmlParser object - $oXmlParser = new XeXmlParser(); // Open an index file $f = fopen($index_file,"r"); // Pass if already read @@ -552,7 +543,7 @@ class importerAdminController extends importer // Find a location $target_file = trim(fgets($f, 1024)); // Load and parse the file - $xmlObj = $oXmlParser->loadXmlFile($target_file); + $xmlObj = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($target_file); FileHandler::removeFile($target_file); if(!$xmlObj) continue; // List objects @@ -638,8 +629,6 @@ class importerAdminController extends importer */ function importModule($key, $cur, $index_file, $module_srl) { - // Pre-create the objects needed - $this->oXmlParser = new XeXmlParser(); // Get category information of the target module $oDocumentController = getController('document'); $oDocumentModel = getModel('document'); @@ -651,9 +640,7 @@ class importerAdminController extends importer if(file_exists($category_file)) { $buff = FileHandler::readFile($category_file); - - // Create the xmlParser object - $xmlDoc = $this->oXmlParser->loadXmlFile($category_file); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($category_file); $categories = $xmlDoc->items->category; if($categories) @@ -757,7 +744,7 @@ class importerAdminController extends importer if($started) $buff[] = $str; } - $xmlDoc = $this->oXmlParser->parse(implode('', $buff)); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString(implode('', $buff)); $category = base64_decode($xmlDoc->post->category->body); if($category_titles[$category]) $obj->category_srl = $category_titles[$category]; @@ -901,7 +888,7 @@ class importerAdminController extends importer // If , insert to the DB if(trim($str) == '') { - $xmlDoc = $this->oXmlParser->parse($buff); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff); $obj = new stdClass; $obj->trackback_srl = getNextSequence(); @@ -963,7 +950,7 @@ class importerAdminController extends importer // If is, insert to the DB if(trim($str) == '') { - $xmlDoc = $this->oXmlParser->parse($buff); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff); $sequence = base64_decode($xmlDoc->comment->sequence->body); $sequences[$sequence] = $obj->comment_srl; @@ -1106,7 +1093,7 @@ class importerAdminController extends importer // If it ends with , handle attachements if(trim($str) == '') { - $xmlDoc = $this->oXmlParser->parse($buff.$str); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff.$str); $file_obj->source_filename = base64_decode($xmlDoc->attach->filename->body); $file_obj->download_count = base64_decode($xmlDoc->attach->download_count->body); @@ -1250,14 +1237,13 @@ class importerAdminController extends importer if(!$buff) return array(); $buff = ''.$buff; - $oXmlParser = new XeXmlParser(); - $xmlDoc = $this->oXmlParser->parse($buff); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff); if(empty($xmlDoc->extra_vars->key)) return array(); $index = 1; foreach($xmlDoc->extra_vars->key as $k => $v) { - unset($vobj); + $vobj = new stdClass(); if($v->var_idx) { $vobj->var_idx = base64_decode($v->var_idx->body); diff --git a/modules/krzip/krzip.model.php b/modules/krzip/krzip.model.php index c5749f63d..e571bdc5d 100644 --- a/modules/krzip/krzip.model.php +++ b/modules/krzip/krzip.model.php @@ -173,8 +173,7 @@ class krzipModel extends krzip $request_config ); - $oXmlParser = new XeXmlParser(); - $result = $oXmlParser->parse($buff); + $result = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff); if($result->error) { $err_msg = trim($result->error->message->body); diff --git a/modules/layout/layout.model.php b/modules/layout/layout.model.php index b3f2f96ad..b8f047fec 100644 --- a/modules/layout/layout.model.php +++ b/modules/layout/layout.model.php @@ -572,13 +572,17 @@ class LayoutModel extends Layout return $layout_info; } // If no cache file exists, parse the xml and then return the variable. - $oXmlParser = new XeXmlParser(); - $tmp_xml_obj = $oXmlParser->loadXmlFile($xml_file); + $tmp_xml_obj = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($xml_file); + if (!$tmp_xml_obj) + { + return; + } - if($tmp_xml_obj->layout) $xml_obj = $tmp_xml_obj->layout; - elseif($tmp_xml_obj->skin) $xml_obj = $tmp_xml_obj->skin; - - if(!$xml_obj) return; + $xml_obj = !empty($tmp_xml_obj->layout) ? $tmp_xml_obj->layout : $tmp_xml_obj->skin; + if (!$xml_obj) + { + return; + } $buff = array(); $buff[] = '$layout_info = new stdClass;'; diff --git a/modules/module/module.model.php b/modules/module/module.model.php index e2a43e5d3..7ed46d06b 100644 --- a/modules/module/module.model.php +++ b/modules/module/module.model.php @@ -1031,8 +1031,7 @@ class ModuleModel extends Module } // Create XmlParser object - $oXmlParser = new XeXmlParser(); - $_xml_obj = $oXmlParser->loadXmlFile($skin_xml_file); + $_xml_obj = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($skin_xml_file); // Return if no skin information is if(!$_xml_obj->skin) return; $xml_obj = $_xml_obj->skin; From 3f6dbf847dfeed100e19924bb7f116642d24e177 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Sun, 18 May 2025 22:04:18 +0900 Subject: [PATCH 10/69] Remove references to old XeXmlParser in widget module --- modules/widget/widget.controller.php | 7 ++----- modules/widget/widget.model.php | 10 ++++------ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/modules/widget/widget.controller.php b/modules/widget/widget.controller.php index 0ba27cf30..4f87a6500 100644 --- a/modules/widget/widget.controller.php +++ b/modules/widget/widget.controller.php @@ -301,8 +301,7 @@ class WidgetController extends Widget function transWidgetBox($matches) { $buff = preg_replace('/
(.*)$/i','
',$matches[0]); - $oXmlParser = new XeXmlParser(); - $xml_doc = $oXmlParser->parse($buff); + $xml_doc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff); $vars = $xml_doc->div->attrs; $widget = $vars->widget; @@ -324,13 +323,11 @@ class WidgetController extends Widget // Bringing widget cache sequence preg_match_all('!]*)widget=([^\>]*?)\>!is', $content, $matches); - $oXmlParser = new XeXmlParser(); - $cnt = count($matches[1]); for($i=0;$i<$cnt;$i++) { $buff = $matches[0][$i]; - $xml_doc = $oXmlParser->parse(trim($buff)); + $xml_doc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString(trim($buff)); $args = $xml_doc->img->attrs; $widget = $args->widget; if(!$args || !$widget || empty($args->widget_cache)) diff --git a/modules/widget/widget.model.php b/modules/widget/widget.model.php index cedf80bbc..78f5651be 100644 --- a/modules/widget/widget.model.php +++ b/modules/widget/widget.model.php @@ -137,9 +137,8 @@ class WidgetModel extends Widget return $widget_info; } // If no cache file exists, parse the xml and then return the variable. - $oXmlParser = new XeXmlParser(); - $tmp_xml_obj = $oXmlParser->loadXmlFile($xml_file); - $xml_obj = $tmp_xml_obj->widget; + $tmp_xml_obj = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($xml_file); + $xml_obj = $tmp_xml_obj->widget ?? null; if(!$xml_obj) return; $buff = '$widget_info = new stdClass;'; @@ -287,9 +286,8 @@ class WidgetModel extends Widget return $widgetStyle_info; } // If no cache file exists, parse the xml and then return the variable. - $oXmlParser = new XeXmlParser(); - $tmp_xml_obj = $oXmlParser->loadXmlFile($xml_file); - $xml_obj = $tmp_xml_obj->widgetstyle; + $tmp_xml_obj = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($xml_file); + $xml_obj = $tmp_xml_obj->widgetstyle ?? null; if(!$xml_obj) return; $buff = array(); From 86118dbf505300659280ceff6c2373a91c182592 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 May 2025 20:56:22 +0900 Subject: [PATCH 11/69] Update XML parsers for more backward compatibility --- common/framework/parsers/AddonInfoParser.php | 19 +++---- common/framework/parsers/BaseParser.php | 57 +++++++++++++++++-- .../parsers/EditorComponentParser.php | 53 ++++++++++++----- 3 files changed, 99 insertions(+), 30 deletions(-) diff --git a/common/framework/parsers/AddonInfoParser.php b/common/framework/parsers/AddonInfoParser.php index 3ea9c820f..683e41a66 100644 --- a/common/framework/parsers/AddonInfoParser.php +++ b/common/framework/parsers/AddonInfoParser.php @@ -41,7 +41,7 @@ class AddonInfoParser extends BaseParser $info->description = self::_getChildrenByLang($xml, 'description', $lang); $info->version = trim($xml->version); $info->date = ($xml->date === 'RX_CORE') ? '' : date('Ymd', strtotime($xml->date . 'T12:00:00Z')); - $info->homepage = trim($xml->homepage); + $info->homepage = trim($xml->link); $info->license = trim($xml->license); $info->license_link = trim($xml->license['link'] ?? ''); $info->author = array(); @@ -63,25 +63,22 @@ class AddonInfoParser extends BaseParser $info->description = self::_getChildrenByLang($xml->author, 'description', $lang); $info->version = trim($xml['version'] ?? ''); $info->date = date('Ymd', strtotime($xml->author['date'] . 'T12:00:00Z')); - $info->homepage = trim($xml->homepage); + $info->homepage = trim($xml->link); $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::_getChildrenByLang($author, 'name', $lang); - $author_info->email_address = trim($author['email_address']); - $author_info->homepage = trim($author['link'] ?? ''); - $info->author[] = $author_info; - } + $author_info = new \stdClass; + $author_info->name = self::_getChildrenByLang($xml->author, 'name', $lang); + $author_info->email_address = trim($xml->author['email_address']); + $author_info->homepage = trim($xml->author['link'] ?? ''); + $info->author[] = $author_info; } // Get extra_vars. if ($xml->extra_vars) { - $info->extra_vars = get_object_vars(self::_getExtraVars($xml->extra_vars, $lang)); + $info->extra_vars = get_object_vars(self::_getExtraVars($xml->extra_vars, $lang, 'addon')); } // Prepare additional fields that will be filled in later. diff --git a/common/framework/parsers/BaseParser.php b/common/framework/parsers/BaseParser.php index 0c1fb111b..d93b3dfb0 100644 --- a/common/framework/parsers/BaseParser.php +++ b/common/framework/parsers/BaseParser.php @@ -109,26 +109,62 @@ abstract class BaseParser * * @param \SimpleXMLElement $extra_vars * @param string $lang + * @param string $type * @return object */ - protected static function _getExtraVars(\SimpleXMLElement $extra_vars, string $lang): \stdClass + protected static function _getExtraVars(\SimpleXMLElement $extra_vars, string $lang, string $type = ''): \stdClass { $result = new \stdClass; + + // Recurse into groups. $group_name = $extra_vars->getName() === 'group' ? self::_getChildrenByLang($extra_vars, 'title', $lang) : null; foreach ($extra_vars->group ?: [] as $group) { - $group_result = self::_getExtraVars($group, $lang); + $group_result = self::_getExtraVars($group, $lang, $type); foreach ($group_result as $key => $val) { $result->{$key} = $val; } } + + // Parse each variable in the group. foreach ($extra_vars->var ?: [] as $var) { $item = new \stdClass; $item->group = $group_name; - $item->name = trim($var['name']); - $item->type = trim($var['type']) ?: 'text'; + + // id and name + if ($type === 'widget') + { + $item->id = trim($var['id']) ?: trim($var->id); + if (!$item->id) + { + $item->id = trim($var['name']); + } + $item->name = $var->nameself::_getChildrenByLang($var, 'name', $lang); + if (!$item->name) + { + $item->name = self::_getChildrenByLang($var, 'title', $lang); + } + } + else + { + $item->name = trim($var['name']); + } + + // type + $item->type = trim($var['type']); + if (!$item->type) + { + $item->type = trim($var->type) ?: 'text'; + } + if ($item->type === 'filebox' && isset($var->type)) + { + $item->filter = trim($var->type['filter'] ?? ''); + $item->allow_multiple = trim($var->type['allow_multiple'] ?? ''); + } + + // Other common attributes $item->title = self::_getChildrenByLang($var, 'title', $lang); $item->description = str_replace('\\n', "\n", self::_getChildrenByLang($var, 'description', $lang)); $item->default = trim($var['default']) ?: null; @@ -137,6 +173,8 @@ abstract class BaseParser $item->default = self::_getChildrenByLang($var, 'default', $lang); } $item->value = null; + + // Options if ($var->options) { $item->options = array(); @@ -144,13 +182,22 @@ abstract class BaseParser { $option_item = new \stdClass; $option_item->title = self::_getChildrenByLang($option, 'title', $lang); - $option_item->value = trim($option['value']); + $option_item->value = trim($option['value']) ?: trim($option->value); $item->options[$option_item->value] = $option_item; + if ($type === 'widget' && $option['default'] === 'true') + { + $item->default_options[$option_item->value] = true; + } + if ($type === 'widget' && $option['init'] === 'true') + { + $item->init_options[$option_item->value] = true; + } } } $result->{$item->name} = $item; } + return $result; } } diff --git a/common/framework/parsers/EditorComponentParser.php b/common/framework/parsers/EditorComponentParser.php index a50036ab6..4db0fcac2 100644 --- a/common/framework/parsers/EditorComponentParser.php +++ b/common/framework/parsers/EditorComponentParser.php @@ -31,29 +31,54 @@ class EditorComponentParser extends BaseParser $info = new \stdClass; $info->component_name = $component_name; - // Get basic information. - $info->title = self::_getChildrenByLang($xml, 'title', $lang); - $info->description = self::_getChildrenByLang($xml, 'description', $lang); - $info->version = trim($xml->version ?? ''); - $info->date = date('Ymd', strtotime($xml->date . 'T12:00:00Z')); - $info->homepage = trim($xml->homepage ?? ''); - $info->license = trim($xml->license ?? ''); - $info->license_link = trim($xml->license['link'] ?? ''); - $info->author = array(); + // Get the XML schema version. + $version = strval($xml['version']) ?: '0.1'; - foreach ($xml->author as $author) + // Parse version 0.2 + if ($version === '0.2') { + $info->title = self::_getChildrenByLang($xml, 'title', $lang); + $info->description = self::_getChildrenByLang($xml, 'description', $lang); + $info->version = trim($xml->version ?? ''); + $info->date = date('Ymd', strtotime($xml->date . 'T12:00:00Z')); + $info->homepage = trim($xml->link); + $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::_getChildrenByLang($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::_getChildrenByLang($xml, 'title', $lang); + $info->description = self::_getChildrenByLang($xml->author, 'description', $lang); + $info->version = trim($xml['version'] ?? ''); + $info->date = date('Ymd', strtotime($xml->author['date'] . 'T12:00:00Z')); + $info->homepage = trim($xml->link) ?: trim($xml->homepage); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link'] ?? ''); + $info->author = array(); + $author_info = new \stdClass; - $author_info->name = self::_getChildrenByLang($author, 'name', $lang); - $author_info->email_address = trim($author['email_address'] ?? ''); - $author_info->homepage = trim($author['link'] ?? ''); + $author_info->name = self::_getChildrenByLang($xml->author, 'name', $lang); + $author_info->email_address = trim($xml->author['email_address']); + $author_info->homepage = trim($xml->author['link'] ?? ''); $info->author[] = $author_info; } // Get extra_vars. if ($xml->extra_vars) { - $info->extra_vars = self::_getExtraVars($xml->extra_vars, $lang); + $info->extra_vars = self::_getExtraVars($xml->extra_vars, $lang, 'editor_component'); } // Return the complete result. From 6727b124cdd3e236c5877014b3839508d4d8adef Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 May 2025 21:29:25 +0900 Subject: [PATCH 12/69] Always initialize extra_vars attribute --- common/framework/parsers/AddonInfoParser.php | 4 ++++ common/framework/parsers/EditorComponentParser.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/common/framework/parsers/AddonInfoParser.php b/common/framework/parsers/AddonInfoParser.php index 683e41a66..7598ed141 100644 --- a/common/framework/parsers/AddonInfoParser.php +++ b/common/framework/parsers/AddonInfoParser.php @@ -80,6 +80,10 @@ class AddonInfoParser extends BaseParser { $info->extra_vars = get_object_vars(self::_getExtraVars($xml->extra_vars, $lang, 'addon')); } + else + { + $info->extra_vars = []; + } // Prepare additional fields that will be filled in later. $info->is_enabled = (object)['pc' => false, 'mobile' => false]; diff --git a/common/framework/parsers/EditorComponentParser.php b/common/framework/parsers/EditorComponentParser.php index 4db0fcac2..53ea89118 100644 --- a/common/framework/parsers/EditorComponentParser.php +++ b/common/framework/parsers/EditorComponentParser.php @@ -80,6 +80,10 @@ class EditorComponentParser extends BaseParser { $info->extra_vars = self::_getExtraVars($xml->extra_vars, $lang, 'editor_component'); } + else + { + $info->extra_vars = new \stdClass; + } // Return the complete result. return $info; From 278369b70e7a13d275b511697cdb66b50436c4c9 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 May 2025 21:38:58 +0900 Subject: [PATCH 13/69] Replace widget and widgetstyle XML parsing and caching logic --- common/framework/parsers/BaseParser.php | 48 ++- common/framework/parsers/WidgetInfoParser.php | 96 ++++++ .../parsers/WidgetStyleInfoParser.php | 83 ++++++ modules/widget/widget.model.php | 281 +++--------------- 4 files changed, 258 insertions(+), 250 deletions(-) create mode 100644 common/framework/parsers/WidgetInfoParser.php create mode 100644 common/framework/parsers/WidgetStyleInfoParser.php diff --git a/common/framework/parsers/BaseParser.php b/common/framework/parsers/BaseParser.php index d93b3dfb0..37fbcb0bb 100644 --- a/common/framework/parsers/BaseParser.php +++ b/common/framework/parsers/BaseParser.php @@ -134,14 +134,14 @@ abstract class BaseParser $item->group = $group_name; // id and name - if ($type === 'widget') + if ($type === 'widget' || $type === 'widgetstyle') { - $item->id = trim($var['id']) ?: trim($var->id); + $item->id = trim($var['id'] ?? '') ?: trim($var->id); if (!$item->id) { - $item->id = trim($var['name']); + $item->id = trim($var['name'] ?? ''); } - $item->name = $var->nameself::_getChildrenByLang($var, 'name', $lang); + $item->name = self::_getChildrenByLang($var, 'name', $lang); if (!$item->name) { $item->name = self::_getChildrenByLang($var, 'title', $lang); @@ -149,11 +149,11 @@ abstract class BaseParser } else { - $item->name = trim($var['name']); + $item->name = trim($var['name'] ?? ''); } // type - $item->type = trim($var['type']); + $item->type = trim($var['type'] ?? ''); if (!$item->type) { $item->type = trim($var->type) ?: 'text'; @@ -167,7 +167,7 @@ abstract class BaseParser // Other common attributes $item->title = self::_getChildrenByLang($var, 'title', $lang); $item->description = str_replace('\\n', "\n", self::_getChildrenByLang($var, 'description', $lang)); - $item->default = trim($var['default']) ?: null; + $item->default = trim($var['default'] ?? '') ?: null; if (!isset($item->default)) { $item->default = self::_getChildrenByLang($var, 'default', $lang); @@ -180,22 +180,38 @@ abstract class BaseParser $item->options = array(); foreach ($var->options as $option) { - $option_item = new \stdClass; - $option_item->title = self::_getChildrenByLang($option, 'title', $lang); - $option_item->value = trim($option['value']) ?: trim($option->value); - $item->options[$option_item->value] = $option_item; - if ($type === 'widget' && $option['default'] === 'true') + if ($type === 'widget' || $type === 'widgetstyle') { - $item->default_options[$option_item->value] = true; + $value = trim($option->value ?? ''); + $item->options[$value] = self::_getChildrenByLang($option, 'name', $lang); + if ($option['default'] === 'true') + { + $item->default_options[$value] = true; + } + if ($option['init'] === 'true') + { + $item->init_options[$value] = true; + } } - if ($type === 'widget' && $option['init'] === 'true') + else { - $item->init_options[$option_item->value] = true; + $option_item = new \stdClass; + $option_item->title = self::_getChildrenByLang($option, 'title', $lang); + $option_item->value = trim($option['value'] ?? '') ?: trim($option->value ?? ''); + $item->options[$option_item->value] = $option_item; } } } - $result->{$item->name} = $item; + // Add to list of variables + if ($type === 'widget' || $type === 'widgetstyle') + { + $result->{$item->id} = $item; + } + else + { + $result->{$item->name} = $item; + } } return $result; diff --git a/common/framework/parsers/WidgetInfoParser.php b/common/framework/parsers/WidgetInfoParser.php new file mode 100644 index 000000000..6e89979d7 --- /dev/null +++ b/common/framework/parsers/WidgetInfoParser.php @@ -0,0 +1,96 @@ +widget = $widget_name; + $info->path = sprintf('./widgets/%s/', $widget_name); + + // Get the XML schema version. + $version = strval($xml['version']) ?: '0.1'; + + // Parse version 0.2 + if ($version === '0.2') + { + $info->title = self::_getChildrenByLang($xml, 'title', $lang); + $info->description = self::_getChildrenByLang($xml, 'description', $lang); + $info->version = trim($xml->version); + $info->date = ($xml->date === 'RX_CORE') ? '' : date('Ymd', strtotime($xml->date . 'T12:00:00Z')); + $info->homepage = trim($xml->link); + $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::_getChildrenByLang($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::_getChildrenByLang($xml, 'title', $lang); + $info->description = self::_getChildrenByLang($xml->author, 'description', $lang); + $info->version = trim($xml['version'] ?? ''); + $info->date = date('Ymd', strtotime($xml->author['date'] . 'T12:00:00Z')); + $info->homepage = trim($xml->link); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link'] ?? ''); + $info->author = array(); + + $author_info = new \stdClass; + $author_info->name = self::_getChildrenByLang($xml->author, 'name', $lang); + $author_info->email_address = trim($xml->author['email_address']); + $author_info->homepage = trim($xml->author['link'] ?? ''); + $info->author[] = $author_info; + } + + // Get extra_vars. + if ($xml->extra_vars) + { + $info->extra_var = self::_getExtraVars($xml->extra_vars, $lang, 'widget'); + } + else + { + $info->extra_var = new \stdClass; + } + + // Prepare additional fields that will be filled in later. + $info->widget_srl = null; + $info->widget_title = null; + + // Return the complete result. + return $info; + } +} diff --git a/common/framework/parsers/WidgetStyleInfoParser.php b/common/framework/parsers/WidgetStyleInfoParser.php new file mode 100644 index 000000000..f7ae4307d --- /dev/null +++ b/common/framework/parsers/WidgetStyleInfoParser.php @@ -0,0 +1,83 @@ +widgetStyle = $widgetstyle_name; + $info->path = sprintf('./widgetstyles/%s/', $widgetstyle_name); + + // Parse common fields. + $info->title = self::_getChildrenByLang($xml, 'title', $lang); + $info->description = self::_getChildrenByLang($xml, 'description', $lang); + $info->version = trim($xml->version); + $info->date = ($xml->date === 'RX_CORE') ? '' : date('Ymd', strtotime($xml->date . 'T12:00:00Z')); + $info->homepage = trim($xml->link); + $info->license = trim($xml->license); + $info->license_link = trim($xml->license['link'] ?? ''); + + // Parse the preview image. + $preview_filename = trim($xml->preview ?? 'preview.jpg'); + $preview_path = sprintf('%s%s', $info->path, $preview_filename); + if (file_exists($preview_path)) + { + $info->preview = $preview_path; + } + else + { + $info->preview = null; + } + + // Parse the author list. + $info->author = array(); + foreach ($xml->author as $author) + { + $author_info = new \stdClass; + $author_info->name = self::_getChildrenByLang($author, 'name', $lang); + $author_info->email_address = trim($author['email_address'] ?? ''); + $author_info->homepage = trim($author['link'] ?? ''); + $info->author[] = $author_info; + } + + // Get extra_vars. + if ($xml->extra_vars) + { + $info->extra_var = self::_getExtraVars($xml->extra_vars, $lang, 'widget'); + } + else + { + $info->extra_var = new \stdClass; + } + + // Count extra vars. + $info->extra_var_count = count(get_object_vars($info->extra_var)); + + // Return the complete result. + return $info; + } +} diff --git a/modules/widget/widget.model.php b/modules/widget/widget.model.php index 78f5651be..a851dd5ca 100644 --- a/modules/widget/widget.model.php +++ b/modules/widget/widget.model.php @@ -122,147 +122,38 @@ class WidgetModel extends Widget */ function getWidgetInfo($widget) { - // Get a path of the requested module. Return if not exists. + // Check the widget path. + $widget = preg_replace('/[^a-zA-Z0-9-_]/', '', $widget); $widget_path = $this->getWidgetPath($widget); - if(!$widget_path) return; - // Read the xml file for module skin information - $xml_file = sprintf("%sconf/info.xml", $widget_path); - if(!file_exists($xml_file)) return; - // If the problem by comparing the cache file and include the return variable $widget_info - $cache_file = sprintf(RX_BASEDIR . 'files/cache/widget/%s.%s.cache.php', $widget, Context::getLangType()); - - if(file_exists($cache_file)&&filemtime($cache_file)>filemtime($xml_file)) + if (!$widget_path) + { + return; + } + + // Check the XML file. + $xml_file = sprintf("%sconf/info.xml", $widget_path); + if (!file_exists($xml_file)) + { + return; + } + + // Check the cache. + $xml_mtime = filemtime($xml_file); + $cache_key = sprintf('widget_info:%s:%d', $widget, $xml_mtime); + $widget_info = Rhymix\Framework\Cache::get($cache_key); + if ($widget_info) { - @include($cache_file); return $widget_info; } - // If no cache file exists, parse the xml and then return the variable. - $tmp_xml_obj = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($xml_file); - $xml_obj = $tmp_xml_obj->widget ?? null; - if(!$xml_obj) return; - $buff = '$widget_info = new stdClass;'; - - if($xml_obj->version && $xml_obj->attrs->version == '0.2') + // Parse the XML file and store the result in the cache. + $widget_info = Rhymix\Framework\Parsers\WidgetInfoParser::loadXML($xml_file, $widget); + if (!$widget_info) { - // Title of the widget, version - $buff .= sprintf('$widget_info->widget = %s;', var_export($widget, true)); - $buff .= sprintf('$widget_info->path = %s;', var_export($widget_path, true)); - $buff .= sprintf('$widget_info->title = %s;', var_export($xml_obj->title->body, true)); - $buff .= sprintf('$widget_info->description = %s;', var_export($xml_obj->description->body, true)); - $buff .= sprintf('$widget_info->version = %s;', var_export($xml_obj->version->body, true)); - if($xml_obj->date->body === 'RX_CORE') - { - $date = ''; - } - else - { - $date_obj = new stdClass; - sscanf($xml_obj->date->body, '%d-%d-%d', $date_obj->y, $date_obj->m, $date_obj->d); - $date = sprintf('%04d%02d%02d', $date_obj->y, $date_obj->m, $date_obj->d); - } - $buff .= sprintf('$widget_info->date = %s;', var_export($date, true)); - $buff .= sprintf('$widget_info->homepage = %s;', var_export($xml_obj->link->body, true)); - $buff .= sprintf('$widget_info->license = %s;', var_export($xml_obj->license->body, true)); - $buff .= sprintf('$widget_info->license_link = %s;', var_export($xml_obj->license->attrs->link, true)); - $buff .= sprintf('$widget_info->widget_srl = $widget_srl;'); - $buff .= sprintf('$widget_info->widget_title = $widget_title;'); - // Author information - if(!is_array($xml_obj->author)) $author_list[] = $xml_obj->author; - else $author_list = $xml_obj->author; - - for($i=0; $i < count($author_list); $i++) - { - $buff .= '$widget_info->author['.$i.'] = new stdClass;'; - $buff .= sprintf('$widget_info->author['.$i.']->name = %s;', var_export($author_list[$i]->name->body, true)); - $buff .= sprintf('$widget_info->author['.$i.']->email_address = %s;', var_export($author_list[$i]->attrs->email_address, true)); - $buff .= sprintf('$widget_info->author['.$i.']->homepage = %s;', var_export($author_list[$i]->attrs->link, true)); - } - } - else - { - // Title of the widget, version - $buff .= sprintf('$widget_info->widget = %s;', var_export($widget, true)); - $buff .= sprintf('$widget_info->path = %s;', var_export($widget_path, true)); - $buff .= sprintf('$widget_info->title = %s;', var_export($xml_obj->title->body, true)); - $buff .= sprintf('$widget_info->description = %s;', var_export($xml_obj->author->description->body, true)); - $buff .= sprintf('$widget_info->version = %s;', var_export($xml_obj->attrs->version, true)); - $date_obj = new stdClass; - sscanf($xml_obj->author->attrs->date, '%d. %d. %d', $date_obj->y, $date_obj->m, $date_obj->d); - $date = sprintf('%04d%02d%02d', $date_obj->y, $date_obj->m, $date_obj->d); - $buff .= sprintf('$widget_info->date = %s;', var_export($date, true)); - $buff .= sprintf('$widget_info->widget_srl = $widget_srl;'); - $buff .= sprintf('$widget_info->widget_title = $widget_title;'); - // Author information - $buff .= '$widget_info->author[0] = new stdClass;'; - $buff .= sprintf('$widget_info->author[0]->name = %s;', var_export($xml_obj->author->name->body, true)); - $buff .= sprintf('$widget_info->author[0]->email_address = %s;', var_export($xml_obj->author->attrs->email_address, true)); - $buff .= sprintf('$widget_info->author[0]->homepage = %s;', var_export($xml_obj->author->attrs->link, true)); - } - // Extra vars (user defined variables to use in a template) - $extra_var_groups = $xml_obj->extra_vars->group; - if(!$extra_var_groups) $extra_var_groups = $xml_obj->extra_vars; - if(!is_array($extra_var_groups)) $extra_var_groups = array($extra_var_groups); - foreach($extra_var_groups as $group) - { - $extra_vars = $group->var; - if(!is_array($group->var)) $extra_vars = array($group->var); - - if($extra_vars[0]->attrs->id || $extra_vars[0]->attrs->name) - { - $extra_var_count = count($extra_vars); - - $buff .= sprintf('$widget_info->extra_var_count = %d;', $extra_var_count); - $buff .= '$widget_info->extra_var = $widget_info->extra_var ?? new stdClass;'; - for($i=0;$i<$extra_var_count;$i++) - { - unset($var); - unset($options); - $var = $extra_vars[$i]; - - $id = $var->attrs->id?$var->attrs->id:$var->attrs->name; - $name = $var->name->body?$var->name->body:$var->title->body; - $type = $var->attrs->type?$var->attrs->type:$var->type->body; - $buff .= sprintf('$widget_info->extra_var->%s = new stdClass;', $id); - if($type =='filebox') - { - $buff .= sprintf('$widget_info->extra_var->%s->filter = %s;', $id, var_export($var->type->attrs->filter, true)); - $buff .= sprintf('$widget_info->extra_var->%s->allow_multiple = %s;', $id, var_export($var->type->attrs->allow_multiple, true)); - } - - $buff .= sprintf('$widget_info->extra_var->%s->group = %s;', $id, var_export($group->title->body, true)); - $buff .= sprintf('$widget_info->extra_var->%s->name = %s;', $id, var_export($name, true)); - $buff .= sprintf('$widget_info->extra_var->%s->type = %s;', $id, var_export($type, true)); - $buff .= sprintf('$widget_info->extra_var->%s->value = $vars->%s;', $id, $id); - $buff .= sprintf('$widget_info->extra_var->%s->description = %s;', $id, var_export($var->description->body, true)); - - $options = $var->options; - if(!$options) continue; - - if(!is_array($options)) $options = array($options); - $options_count = count($options); - for($j=0;$j<$options_count;$j++) - { - $buff .= sprintf('$widget_info->extra_var->%s->options[%s] = %s;', $id, var_export($options[$j]->value->body, true), var_export($options[$j]->name->body, true)); - - if($options[$j]->attrs->default && $options[$j]->attrs->default=='true') - { - $buff .= sprintf('$widget_info->extra_var->%s->default_options[%s] = true;', $id, var_export($options[$j]->value->body, true)); - } - - if($options[$j]->attrs->init && $options[$j]->attrs->init=='true') - { - $buff .= sprintf('$widget_info->extra_var->%s->init_options[%s] = true;', $id, var_export($options[$j]->value->body, true)); - } - } - } - } + return; } - $buff = ''; - FileHandler::writeFile($cache_file, $buff); - - if(file_exists($cache_file)) @include($cache_file); + Rhymix\Framework\Cache::set($cache_key, $widget_info); return $widget_info; } @@ -272,116 +163,38 @@ class WidgetModel extends Widget */ function getWidgetStyleInfo($widgetStyle) { + // Check the widget style path. $widgetStyle = preg_replace('/[^a-zA-Z0-9-_]/', '', $widgetStyle); $widgetStyle_path = $this->getWidgetStylePath($widgetStyle); - if(!$widgetStyle_path) return; - $xml_file = sprintf("%sskin.xml", $widgetStyle_path); - if(!file_exists($xml_file)) return; - // If the problem by comparing the cache file and include the return variable $widgetStyle_info - $cache_file = sprintf(RX_BASEDIR . 'files/cache/widgetstyles/%s.%s.cache.php', $widgetStyle, Context::getLangType()); - - if(file_exists($cache_file)&&filemtime($cache_file)>filemtime($xml_file)) + if (!$widgetStyle_path) + { + return; + } + + // Check the XML file. + $xml_file = $widgetStyle_path . 'skin.xml'; + if (!file_exists($xml_file)) + { + return; + } + + // Check the cache. + $xml_mtime = filemtime($xml_file); + $cache_key = sprintf('widgetstyle_info:%s:%d', $widgetStyle, $xml_mtime); + $widgetStyle_info = Rhymix\Framework\Cache::get($cache_key); + if ($widgetStyle_info) { - @include($cache_file); return $widgetStyle_info; } - // If no cache file exists, parse the xml and then return the variable. - $tmp_xml_obj = Rhymix\Framework\Parsers\XEXMLParser::loadXMLFile($xml_file); - $xml_obj = $tmp_xml_obj->widgetstyle ?? null; - if(!$xml_obj) return; - $buff = array(); - $buff[] = 'widgetStyle = %s;', var_export($widgetStyle, true)); - $buff[] = sprintf('$widgetStyle_info->path = %s;', var_export($widgetStyle_path, true)); - $buff[] = sprintf('$widgetStyle_info->title = %s;', var_export($xml_obj->title->body, true)); - $buff[] = sprintf('$widgetStyle_info->description = %s;', var_export($xml_obj->description->body, true)); - $buff[] = sprintf('$widgetStyle_info->version = %s;', var_export($xml_obj->version->body, true)); - if($xml_obj->date->body === 'RX_CORE') + // Parse the XML file and store the result in the cache. + $widgetStyle_info = Rhymix\Framework\Parsers\WidgetStyleInfoParser::loadXML($xml_file, $widgetStyle); + if (!$widgetStyle_info) { - $date = ''; - } - else - { - $date_obj = new stdClass; - sscanf($xml_obj->date->body, '%d-%d-%d', $date_obj->y, $date_obj->m, $date_obj->d); - $date = sprintf('%04d%02d%02d', $date_obj->y, $date_obj->m, $date_obj->d); - } - $buff[] = sprintf('$widgetStyle_info->date = %s;', var_export($date, true)); - $buff[] = sprintf('$widgetStyle_info->homepage = %s;', var_export($xml_obj->link->body, true)); - $buff[] = sprintf('$widgetStyle_info->license = %s;', var_export($xml_obj->license->body, true)); - $buff[] = sprintf('$widgetStyle_info->license_link = %s;', var_export($xml_obj->license->attrs->link, true)); - - // preview - if(!isset($xml_obj->preview)) $xml_obj->preview = new stdClass; - if(!isset($xml_obj->preview->body) || !$xml_obj->preview->body) $xml_obj->preview->body = 'preview.jpg'; - $preview_file = sprintf("%s%s", $widgetStyle_path,$xml_obj->preview->body); - if(file_exists($preview_file)) $buff[] = sprintf('$widgetStyle_info->preview = %s;', var_export($preview_file, true)); - - // Author information - if(!is_array($xml_obj->author)) $author_list[] = $xml_obj->author; - else $author_list = $xml_obj->author; - - foreach($author_list as $idx => $author) - { - $buff[] = sprintf('$widgetStyle_info->author[%d] = new stdClass();', $idx); - $buff[] = sprintf('$widgetStyle_info->author[%d]->name = %s;', $idx, var_export($author->name->body, true)); - $buff[] = sprintf('$widgetStyle_info->author[%d]->email_address = %s;', $idx, var_export($author->attrs->email_address, true)); - $buff[] = sprintf('$widgetStyle_info->author[%d]->homepage = %s;', $idx, var_export($author->attrs->link, true)); + return; } - // Extra vars (user defined variables to use in a template) - $extra_var_groups = $xml_obj->extra_vars->group; - if(!$extra_var_groups) $extra_var_groups = $xml_obj->extra_vars; - if(!is_array($extra_var_groups)) $extra_var_groups = array($extra_var_groups); - - $extra_var_count = 0; - $buff[] = '$widgetStyle_info->extra_var = $widgetStyle_info->extra_var ?? new stdClass();'; - foreach($extra_var_groups as $group) - { - $extra_vars = (!is_array($group->var)) ? array($group->var) : $group->var; - - if($extra_vars[0]->attrs->id || $extra_vars[0]->attrs->name) - { - foreach($extra_vars as $var) - { - $extra_var_count++; - $id = ($var->attrs->id) ? $var->attrs->id : $var->attrs->name; - $name = ($var->name->body) ? $var->name->body : $var->title->body; - $type = ($var->attrs->type) ? $var->attrs->type : $var->type->body; - - $buff[] = sprintf('$widgetStyle_info->extra_var->%s = new stdClass();', $id); - $buff[] = sprintf('$widgetStyle_info->extra_var->%s->group = %s;', $id, var_export($group->title->body, true)); - $buff[] = sprintf('$widgetStyle_info->extra_var->%s->name = %s;', $id, var_export($name, true)); - $buff[] = sprintf('$widgetStyle_info->extra_var->%s->type = %s;', $id, var_export($type, true)); - if($type =='filebox') - { - $buff[] = sprintf('$widgetStyle_info->extra_var->%s->filter = %s;', $id, var_export($var->attrs->filter, true)); - $buff[] = sprintf('$widgetStyle_info->extra_var->%s->allow_multiple = %s;', $id, var_export($var->attrs->allow_multiple, true)); - } - $buff[] = sprintf('$widgetStyle_info->extra_var->%s->value = $vars->%s;', $id, $id); - $buff[] = sprintf('$widgetStyle_info->extra_var->%s->description = %s;', $id, var_export($var->description->body, true)); - - if($var->options) - { - $var_options = (!is_array($var->options)) ? array($var->options) : $var->options; - foreach($var_options as $option_item) - { - $buff[] = sprintf('$widgetStyle_info->extra_var->%s->options[%s] = %s;', $id, var_export($option_item->value->body, true), var_export($option_item->name->body, true)); - } - } - } - } - } - $buff[] = sprintf('$widgetStyle_info->extra_var_count = %d;', $extra_var_count); - - FileHandler::writeFile($cache_file, implode(PHP_EOL, $buff)); - - if(file_exists($cache_file)) @include($cache_file); - + Rhymix\Framework\Cache::set($cache_key, $widgetStyle_info); return $widgetStyle_info; } } From ec6ade4e26a59810598c1eb3672c0d7640d260bf Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 May 2025 21:50:16 +0900 Subject: [PATCH 14/69] Replace all remaining use of XE XML Parser with SimpleXML in widget module --- modules/widget/widget.controller.php | 50 +++++++++++++++++----------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/modules/widget/widget.controller.php b/modules/widget/widget.controller.php index 4f87a6500..c19daf630 100644 --- a/modules/widget/widget.controller.php +++ b/modules/widget/widget.controller.php @@ -300,16 +300,24 @@ class WidgetController extends Widget */ function transWidgetBox($matches) { - $buff = preg_replace('/
(.*)$/i','
',$matches[0]); - $xml_doc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString($buff); + $buff = preg_replace('/
(.*)$/i','
', $matches[0]); + $xml = simplexml_load_string(trim($buff)); + $args = new stdClass; + foreach ($xml->div ? $xml->div->attributes() : $xml->attributes() as $key => $val) + { + $args->{$key} = strval($val); + } - $vars = $xml_doc->div->attrs; - $widget = $vars->widget; - if(!$widget) return $matches[0]; + $widget = $args->widget ?? null; + if(!$widget) + { + return $matches[0]; + } + + $args->widgetbox_content = $matches[3]; unset($vars->widget); - $vars->widgetbox_content = $matches[3]; - return $this->execute($widget, $vars, $this->javascript_mode); + return $this->execute($widget, $args, $this->javascript_mode); } /** @@ -320,16 +328,25 @@ class WidgetController extends Widget { // Language in bringing $lang_list = Context::get('lang_supported'); + // Bringing widget cache sequence preg_match_all('!]*)widget=([^\>]*?)\>!is', $content, $matches); - $cnt = count($matches[1]); - for($i=0;$i<$cnt;$i++) + foreach ($matches[0] as $buff) { - $buff = $matches[0][$i]; - $xml_doc = Rhymix\Framework\Parsers\XEXMLParser::loadXMLString(trim($buff)); - $args = $xml_doc->img->attrs; - $widget = $args->widget; + $xml = simplexml_load_string(trim($buff)); + if ($xml === false) + { + continue; + } + + $args = new stdClass; + foreach ($xml->img ? $xml->img->attributes() : $xml->attributes() as $key => $val) + { + $args->{$key} = strval($val); + } + + $widget = $args->widget ?? null; if(!$args || !$widget || empty($args->widget_cache)) { continue; @@ -338,12 +355,7 @@ class WidgetController extends Widget $args->widget_sequence = $args->widget_sequence ?? 0; $args->colorset = $args->colorset ?? null; - foreach($args as $k => $v) - { - $args->{$k} = urldecode($v); - } - - foreach($lang_list as $lang_type => $val) + foreach ($lang_list as $lang_type => $val) { $this->getCache($widget, $args, $lang_type, true); } From ba638c394db23841b8a37876325f83ff5f3e8659 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 May 2025 21:54:09 +0900 Subject: [PATCH 15/69] Replace all remaining reference to XeXmlParser in ttimport.class.php --- modules/importer/ttimport.class.php | 30 +++++++++++------------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/modules/importer/ttimport.class.php b/modules/importer/ttimport.class.php index d6735e582..1e6855ae3 100644 --- a/modules/importer/ttimport.class.php +++ b/modules/importer/ttimport.class.php @@ -13,12 +13,6 @@ */ class ttimport { - /** - * Xml Parse - * @var XmlParser - */ - var $oXmlParser = null; - /** * Import data in module.xml format * @param int $key @@ -33,8 +27,6 @@ class ttimport */ function importModule($key, $cur, $index_file, $unit_count, $module_srl, $guestbook_module_srl, $user_id, $module_name=null) { - // Pre-create the objects needed - $this->oXmlParser = new XeXmlParser(); // Get category information of the target module $oDocumentController = getController('document'); $oDocumentModel = getModel('document'); @@ -45,8 +37,8 @@ class ttimport $category_file = preg_replace('/index$/i', 'category.xml', $index_file); if(file_exists($category_file)) { - // Create the xmlParser object - $xmlDoc = $this->oXmlParser->loadXmlFile($category_file); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXmlFile($category_file); + // List category information if($xmlDoc->categories->category) { @@ -62,7 +54,7 @@ class ttimport $obj = null; $obj->title = $category; - $obj->module_srl = $module_srl; + $obj->module_srl = $module_srl; if($v->parent) $obj->parent_srl = $match_sequence[$v->parent]; $output = $oDocumentController->insertCategory($obj); @@ -126,7 +118,7 @@ class ttimport if($started) $buff .= $str; } - $xmlDoc = $this->oXmlParser->parse(''.$buff); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXmlString(''.$buff); $author_xml_id = $xmlDoc->post->author->body; @@ -250,7 +242,7 @@ class ttimport // Save state if not published if(!in_array($xmlDoc->post->visibility->body, $status_published)) { - $obj->module_srl = $member_info->member_srl; + $obj->module_srl = $member_info->member_srl; } } // Document @@ -288,8 +280,8 @@ class ttimport $guestbook_file = preg_replace('/index$/i', 'guestbook.xml', $index_file); if(file_exists($guestbook_file)) { - // Create the xmlParser object - $xmlDoc = $this->oXmlParser->loadXmlFile($guestbook_file); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXmlFile($guestbook_file); + // Handle guest book information if($guestbook_module_srl && $xmlDoc->guestbook->comment) { @@ -480,7 +472,7 @@ class ttimport $buff .= ''; - $xmlDoc = $this->oXmlParser->parse($buff); + $xmlDoc = Rhymix\Framework\Parsers\XEXMLParser::loadXmlString($buff); $file_obj->source_filename = $xmlDoc->attachment->label->body; $file_obj->download_count = $xmlDoc->attachment->downloads->body; @@ -516,7 +508,7 @@ class ttimport { $uploaded_count++; $tmp_obj = null; - if($file_obj->direct_download == 'Y') $files[$name]->url = $file_obj->uploaded_filename; + if($file_obj->direct_download == 'Y') $files[$name]->url = $file_obj->uploaded_filename; else $files[$name]->url = getUrl('','module','file','act','procFileDownload','file_srl',$file_obj->file_srl,'sid',$file_obj->sid); $files[$name]->direct_download = $file_obj->direct_download; $files[$name]->source_filename = $file_obj->source_filename; @@ -583,7 +575,7 @@ class ttimport if(preg_match('/\.(jpg|gif|jpeg|png)$/i', $obj->source_filename)) { return sprintf('%s', $obj->url, str_replace('"','\\"',$matches[4])); - // If other multimedia file but image is, + // If other multimedia file but image is, } else { @@ -606,7 +598,7 @@ class ttimport $key = $matches[1]; if(!$key) return $matches[0]; - return + return ''. ''. ''. From a77b9a5d3aa560a9ec79d8466963e945d0ed902c Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 May 2025 22:44:32 +0900 Subject: [PATCH 16/69] Implement RulesetParser --- common/framework/parsers/RulesetParser.php | 95 ++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 common/framework/parsers/RulesetParser.php diff --git a/common/framework/parsers/RulesetParser.php b/common/framework/parsers/RulesetParser.php new file mode 100644 index 000000000..1f3fa80dd --- /dev/null +++ b/common/framework/parsers/RulesetParser.php @@ -0,0 +1,95 @@ +rules = []; + $info->messages = []; + $info->filters = []; + $info->fieldsNames = []; + + // Parse custom rules. + if ($xml->customrules && $xml->customrules->rule) + { + foreach ($xml->customrules->rule as $rule) + { + $def = []; + foreach ($rule->attributes() as $key => $val) + { + $def[trim($key)] = trim($val); + } + $def['message'] = self::_getChildrenByLang($rule, 'message', $lang) ?: null; + + $rule_name = trim($rule['name']); + $info->rules[$rule_name] = $def; + + if ($def['message']) + { + $info->messages['invalid_' . $rule_name] = $def['message']; + } + } + } + + // Parse field filters. + if ($xml->fields && $xml->fields->field) + { + foreach ($xml->fields->field as $field) + { + $def = []; + foreach ($field->attributes() as $key => $val) + { + $def[trim($key)] = trim($val); + } + $def['title'] = self::_getChildrenByLang($field, 'title', $lang) ?: null; + + if ($field->if) + { + foreach ($field->if as $if) + { + $condition = []; + foreach ($if->attributes() as $key => $val) + { + $condition[trim($key)] = trim($val); + } + $def['if'][] = $condition; + } + } + + $filter_name = trim($field['name']); + $info->filters[$filter_name] = $def; + + if ($def['title']) + { + $info->fieldsNames[$filter_name] = $def['title']; + } + } + } + + return $info; + } +} From 66e040b3f9e66880d37e55f2973d6b44147cac4c Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 May 2025 23:52:08 +0900 Subject: [PATCH 17/69] Use RulesetParser instead of XeXmlParser in Validator --- classes/validator/Validator.class.php | 150 +++------------------ common/framework/parsers/RulesetParser.php | 2 + 2 files changed, 22 insertions(+), 130 deletions(-) diff --git a/classes/validator/Validator.class.php b/classes/validator/Validator.class.php index 632b35b79..bd6d5c17f 100644 --- a/classes/validator/Validator.class.php +++ b/classes/validator/Validator.class.php @@ -30,31 +30,25 @@ class Validator * rule list * @var array */ - var $_rules; + var $_rules = []; /** * filter list * @var array */ - var $_filters; + var $_filters = []; /** * custom message list * @var array */ - var $_message; + var $_message = []; /** * custom field name list * @var array */ - var $_fieldNames; - - /** - * Can usable status for multibyte string function - * @var boolean - */ - var $_has_mb_func; + var $_fieldNames = []; /** * validator version @@ -75,12 +69,10 @@ class Validator */ function __construct($xml_path = '') { - $this->_rules = array(); - $this->_filters = array(); - $this->_xml_ruleset = NULL; - - if($xml_path) + if ($xml_path) + { $this->load($xml_path); + } // predefined rules $this->addRule(array( @@ -93,8 +85,7 @@ class Validator 'float' => '/^\d+(\.\d+)?$/' )); - $this->_has_mb_func = is_callable('mb_strlen'); - $this->setCacheDir(RX_BASEDIR . 'files/cache'); + $this->_cache_dir = RX_BASEDIR . 'files/cache'; } /** @@ -114,112 +105,26 @@ class Validator */ function load($xml_path) { - $this->_xml_ruleset = NULL; - if(!is_readable($xml_path)) + if (!file_exists($xml_path) || !is_readable($xml_path)) { - return FALSE; + return false; } - $parser = new XeXmlParser(); - $xml = $parser->loadXmlFile($xml_path); - if(!isset($xml->ruleset) || !isset($xml->ruleset->fields) || !isset($xml->ruleset->fields->field)) + $output = Rhymix\Framework\Parsers\RulesetParser::loadXML($xml_path); + if (!$output) { - return FALSE; + return false; } - $rules = array(); - $messages = array(); - - // custom rules - if(isset($xml->ruleset->customrules) && isset($xml->ruleset->customrules->rule)) + if ($output->rules) { - $customrules = $xml->ruleset->customrules->rule; - if(!is_array($customrules)) - { - $customrules = array($customrules); - } - - foreach($customrules as $rule) - { - if(!isset($rule->attrs) || !isset($rule->attrs->name)) - { - continue; - } - - $message = isset($rule->message) ? $rule->message->body : NULL; - $rule = (array) $rule->attrs; - $rule['message'] = $message; - $name = $rule['name']; - unset($rule['name']); - - $rules[$name] = $rule; - if(isset($message)) - { - $messages['invalid_' . $name] = $message; - } - } - if(count($rules)) - { - $this->addRule($rules); - } + $this->addRule($output->rules); } - - // filters - $fields = $xml->ruleset->fields->field; - if(!is_array($fields)) - { - $fields = array($fields); - } - - $filters = array(); - $fieldsNames = array(); - foreach($fields as $field) - { - $name = ''; - $filter = array(); - - if(!isset($field->attrs) || !isset($field->attrs->name)) - { - continue; - } - - $title = isset($field->title) ? $field->title->body : NULL; - $filter = (array) $field->attrs; - $filter['title'] = $title; - - $name = $filter['name']; - if(isset($title)) - { - $fieldsNames[$name] = $title; - } - - unset($filter['name']); - - // conditional statement - if(isset($field->if)) - { - $if = $field->if; - if(!is_array($if)) - { - $if = array($if); - } - foreach($if as $idx => $cond) - { - $if[$idx] = (array) $cond->attrs; - } - $filter['if'] = $if; - } - - $filters[$name] = $filter; - } - - $this->_xml_ruleset = $xml->ruleset; - $this->_filters = $filters; - $this->_message = $messages; - $this->_fieldNames = $fieldsNames; + $this->_filters = $output->filters; + $this->_message = $output->messages; + $this->_fieldNames = $output->fieldsNames; $this->_xml_path = $xml_path; - - return TRUE; + return true; } /** @@ -389,7 +294,7 @@ class Validator $strbytes = strlen($value); if(!$is_min_b || !$is_max_b) { - $strlength = $this->_has_mb_func ? mb_strlen($value, 'utf-8') : $this->mbStrLen($value); + $strlength = mb_strlen($value, 'UTF-8'); } if(($min && $min > ($is_min_b ? $strbytes : $strlength)) || ($max && $max < ($is_max_b ? $strbytes : $strlength))) @@ -630,21 +535,6 @@ class Validator return TRUE; } - /** - * if not supported 'mb_strlen' function, this method can use. - * @param string $str - * @return int - */ - function mbStrLen($str) - { - $arr = count_chars($str); - for($i = 0x80; $i < 0xc0; $i++) - { - unset($arr[$i]); - } - return array_sum($arr); - } - /** * Returns compiled javascript file path. The path begins from XE root directory. * @return string Compiled JavaScript file path diff --git a/common/framework/parsers/RulesetParser.php b/common/framework/parsers/RulesetParser.php index 1f3fa80dd..5fc631524 100644 --- a/common/framework/parsers/RulesetParser.php +++ b/common/framework/parsers/RulesetParser.php @@ -44,6 +44,7 @@ class RulesetParser extends BaseParser $def[trim($key)] = trim($val); } $def['message'] = self::_getChildrenByLang($rule, 'message', $lang) ?: null; + unset($def['name']); $rule_name = trim($rule['name']); $info->rules[$rule_name] = $def; @@ -66,6 +67,7 @@ class RulesetParser extends BaseParser $def[trim($key)] = trim($val); } $def['title'] = self::_getChildrenByLang($field, 'title', $lang) ?: null; + unset($def['name']); if ($field->if) { From 32fa327eb6e89cecda7cd16c2b13fc6058f1e713 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Mon, 19 May 2025 23:57:29 +0900 Subject: [PATCH 18/69] Fix undefined variable warnings --- modules/layout/tpl/layout_info_view.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/layout/tpl/layout_info_view.html b/modules/layout/tpl/layout_info_view.html index a9fbb7322..1d32aa128 100644 --- a/modules/layout/tpl/layout_info_view.html +++ b/modules/layout/tpl/layout_info_view.html @@ -53,10 +53,10 @@

{$lang->extra_vars}

{@$cnt = 1} -
    - +
      +
    • {$var->group}
    • - {@$group = $var->group} + {@$group = $var->group ?? null} {@$cnt ++}
      @@ -77,7 +77,7 @@
      - ") !== false)-->{htmlspecialchars($var->value, ENT_COMPAT | ENT_HTML401, 'UTF-8', false)}{$var->value}" /> +
      @@ -118,7 +118,7 @@
      -
      +
      {$val->val}
      @@ -156,8 +156,8 @@
      - {$lang->cmd_list} - {$lang->cmd_list} + {$lang->cmd_list} + {$lang->cmd_list} From 954ebf6caa93c355f10849f7138dd8e05307ac06 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 20 May 2025 13:28:33 +0900 Subject: [PATCH 19/69] Automaticallly fill default values if addon is turned on without saving config --- modules/addon/addon.admin.controller.php | 23 +++++++++++++++++++++++ modules/addon/addon.controller.php | 24 +++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/modules/addon/addon.admin.controller.php b/modules/addon/addon.admin.controller.php index e6cdb3b2b..6d4cc630f 100644 --- a/modules/addon/addon.admin.controller.php +++ b/modules/addon/addon.admin.controller.php @@ -237,6 +237,29 @@ class addonAdminController extends addonController */ function doInsert($addon, $site_srl = 0, $gtype = 'site', $isUsed = 'N', $extra_vars = null) { + if (!is_object($extra_vars)) + { + $extra_vars = new stdClass(); + } + if (!isset($extra_vars->xe_run_method)) + { + $extra_vars->xe_run_method = 'run_selected'; + } + if (!isset($extra_vars->mid_list) || !is_array($extra_vars->mid_list)) + { + $extra_vars->mid_list = []; + } + + $xml_file = RX_BASEDIR . 'addons/' . $addon . '/conf/info.xml'; + $addon_info = Rhymix\Framework\Parsers\AddonInfoParser::loadXML($xml_file, $addon); + foreach ($addon_info->extra_vars as $key => $val) + { + if (!isset($extra_vars->$key)) + { + $extra_vars->$key = $val->default; + } + } + $args = new stdClass; $args->addon = $addon; if (strlen($isUsed) == 2) diff --git a/modules/addon/addon.controller.php b/modules/addon/addon.controller.php index 95b5c3c9e..c8225c69a 100644 --- a/modules/addon/addon.controller.php +++ b/modules/addon/addon.controller.php @@ -111,7 +111,7 @@ class addonController extends addon $buff[] = sprintf('$addon_file = RX_BASEDIR . \'addons/%s/%s.addon.php\';', $addon, $addon); // Addon configuration - $buff[] = '$addon_info = unserialize(' . var_export(serialize($extra_vars), true) . ');'; + $buff[] = '$addon_info = ' . var_export($extra_vars, true) . ';'; // Decide whether to run in this mid if ($run_method === 'no_run_selected') @@ -159,9 +159,27 @@ class addonController extends addon */ function doSetup($addon, $extra_vars, $site_srl = 0, $gtype = 'site') { - if(!is_array($extra_vars->mid_list)) + if (!is_object($extra_vars)) { - unset($extra_vars->mid_list); + $extra_vars = new stdClass(); + } + if (!isset($extra_vars->xe_run_method)) + { + $extra_vars->xe_run_method = 'run_selected'; + } + if (!isset($extra_vars->mid_list) || !is_array($extra_vars->mid_list)) + { + $extra_vars->mid_list = []; + } + + $xml_file = RX_BASEDIR . 'addons/' . $addon . '/conf/info.xml'; + $addon_info = Rhymix\Framework\Parsers\AddonInfoParser::loadXML($xml_file, $addon); + foreach ($addon_info->extra_vars as $key => $val) + { + if (!isset($extra_vars->$key) && isset($val->default)) + { + $extra_vars->$key = $val->default; + } } $args = new stdClass(); From 6a46c3985159d853ee8690e2515f9a39edbb1a4d Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 20 May 2025 17:38:50 +0900 Subject: [PATCH 20/69] Improve fullscreen iframe handling --- common/css/rhymix.scss | 4 ++++ common/js/common.js | 22 +++++++++++++++++++++- common/tpl/popup_layout.html | 5 +---- modules/admin/tpl/css/admin.css | 8 ++++++-- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/common/css/rhymix.scss b/common/css/rhymix.scss index d116b5b92..91c3e140d 100644 --- a/common/css/rhymix.scss +++ b/common/css/rhymix.scss @@ -10,6 +10,10 @@ article, aside, details, figcaption, figure, footer, header, hgroup, nav, sectio } body { position: relative; + &.rx_modal_open { + overflow: hidden; + position: fixed; + } } a img { border: 0; diff --git a/common/js/common.js b/common/js/common.js index 1558437b9..35f80c911 100644 --- a/common/js/common.js +++ b/common/js/common.js @@ -749,6 +749,7 @@ function openFullScreenIframe(url, target) { const iframe = document.createElement('iframe'); const iframe_sequence = String(Date.now()) + Math.round(Math.random() * 1000000); iframe.setAttribute('id', '_rx_iframe_' + iframe_sequence); + iframe.setAttribute('class', 'rx_fullscreen_iframe'); iframe.setAttribute('name', target || ('_rx_iframe_' + iframe_sequence)) iframe.setAttribute('src', url + '&iframe_sequence=' + iframe_sequence); iframe.setAttribute('width', '100%'); @@ -756,7 +757,26 @@ function openFullScreenIframe(url, target) { iframe.setAttribute('frameborder', '0'); iframe.setAttribute('scrolling', 'no'); iframe.setAttribute('style', 'position:fixed; top:0; left:0; width:100%; height:100%; z-index:999999999; background-color: #fff; overflow-y:auto'); - $(document.body).append(iframe); + + const body = $(document.body); + body.data('rx_scroll_position', { + left: $(window).scrollLeft(), + top: $(window).scrollTop() + }); + body.addClass('rx_modal_open'); + body.append(iframe); +} + +function closeFullScreenIframe() { + $('.rx_fullscreen_iframe').remove(); + const body = $(document.body); + body.removeClass('rx_modal_open'); + const scroll_position = body.data('rx_scroll_position'); + if (scroll_position) { + $(window).scrollLeft(scroll_position.left); + $(window).scrollTop(scroll_position.top); + body.removeData('rx_scroll_position'); + } } /** diff --git a/common/tpl/popup_layout.html b/common/tpl/popup_layout.html index 2378c2672..0c6454a40 100644 --- a/common/tpl/popup_layout.html +++ b/common/tpl/popup_layout.html @@ -11,10 +11,7 @@ const iframe_sequence = '{{ $iframe_sequence }}'; window.opener = window.parent; window.close = function() { - const iframe = parent.document.getElementById('_rx_iframe_' + iframe_sequence); - if (iframe) { - iframe.remove(); - } + parent.closeFullScreenIframe('_rx_iframe_' + iframe_sequence); };