.xml-editor-wrapper{margin:20px 0;padding:12px;background:#111;border:1px solid #222;border-radius:8px} .xml-node{border:1px solid #333;border-radius:6px;padding:12px;margin-bottom:10px;background:#181818} .xml-node__header{display:flex;justify-content:space-between;align-items:center;gap:12px;border-bottom:1px solid #2a2a2a;padding-bottom:6px;margin-bottom:8px} .xml-node__title{font-weight:600;color:#f5f5f5} .xml-node__path{font-size:0.85rem;color:#989898} .xml-node__body label{font-size:0.85rem;color:#bbb;display:block;margin-bottom:4px} .xml-node__body input[type="text"], .xml-node__body textarea, .xml-node__body select{width:100%;padding:8px;border:1px solid #3a3a3a;border-radius:4px;background:#101010;color:#fff;font-family:monospace} .xml-node__body textarea{min-height:120px} .xml-node__attributes{margin-top:8px} .xml-node__attributes .attr-row{display:flex;gap:8px;align-items:center;margin-bottom:6px} .xml-node__attributes .attr-row input[type="text"]{flex:1} .xml-children{margin-top:10px;border-left:2px solid #2a2a2a;padding-left:12px} .xml-actions{display:flex;justify-content:flex-end;margin-top:16px;padding:8px 18px 0} .xml-node__actions{display:flex;gap:8px;align-items:center} .xml-node__apply{background:#1c6dd0;border:1px solid #114b99;color:#fff;padding:6px 12px;border-radius:4px;cursor:pointer} .xml-node__apply:hover{background:#1f7aec} .xml-global-save{background:#1c6dd0;border:1px solid #114b99;color:#fff;padding:10px 28px;border-radius:4px;font-weight:600;text-transform:uppercase;letter-spacing:0.03em;cursor:pointer;transition:background 0.2s ease,transform 0.2s ease;box-shadow:0 2px 6px rgba(0,0,0,0.35)} .xml-global-save:hover{background:#1f7aec;transform:translateY(-1px)} .xml-global-save--top{float:right;margin:0 18px 12px 0} .xml-hint{font-size:0.85rem;color:#999;margin-top:4px} CSS; } function config_games_render_node(SimpleXMLElement $node, array $ancestors, array &$counters, int $depth = 0) { $name = $node->getName(); $pathKey = implode('/', $ancestors) === '' ? $name : implode('/', $ancestors) . '/' . $name; $counters[$pathKey] = ($counters[$pathKey] ?? 0) + 1; $index = $counters[$pathKey]; $pathParts = array_merge($ancestors, ["{$name}[{$index}]"]); $rawPath = implode('/', $pathParts); $path = config_games_normalize_path($rawPath); $hasChildren = count($node->children()) > 0; $value = (string)$node; $safeLabel = htmlspecialchars($name, ENT_QUOTES, 'UTF-8'); $safePath = htmlspecialchars($path, ENT_QUOTES, 'UTF-8'); $nodeKey = config_games_next_form_key(); $safeNodeKey = htmlspecialchars($nodeKey, ENT_QUOTES, 'UTF-8'); $displayPath = htmlspecialchars(str_replace('[', '[', $rawPath), ENT_QUOTES, 'UTF-8'); $isScript = in_array(strtolower($name), ['pre_install','post_install','precmd','postcmd','cli_template']); $html = "
This element contains nested tags; clearing the text does not remove children.
"; } $attributes = $node->attributes(); if ($attributes && count($attributes) > 0) { $html .= "".get_lang_f("modify_configs_info",SERVER_CONFIG_LOCATION)."
\n \n"; if ( isset($_REQUEST['reconfig']) ) { // Remove any old config files that may have been renamed or removed by developers // Function is defined in helpers.php (add entries to array there) removeOldGameConfigs(); $files = glob(SERVER_CONFIG_LOCATION."*.xml"); if ( empty($files) ) { print_failure(get_lang_f("no_configs_found",SERVER_CONFIG_LOCATION)); return; } /// \todo remove the clear_old hack when the update on duplicate is completed to database. $clear_old = FALSE; if ( isset( $_REQUEST['clear_old']) && $_REQUEST['clear_old'] === 'yes' ) { echo "".get_lang('resetting_configs').":
"; $clear_old = TRUE; } else { echo "".get_lang('updating_configs').":
"; } $oldStructure = $db->getCurrentHomeConfigMods(); $db->clearGameCfgs($clear_old); foreach ( $files as $config_file ) { $config = read_server_config($config_file); if ( empty($config) ) { print_failure(get_lang_f("error_when_handling_file",$config_file)); continue; } echo "".get_lang_f("updating_config_from_file",$config_file)."
"; if ( !$db->addGameCfg($config) ) { print_failure(get_lang_f("error_while_adding_cfg_to_db",$config_file)); continue; } } // Update and remove invalid old game mod ids if($clear_old){ $db->updateOGPGameModsWithNewIDs($oldStructure); } print_success(get_lang('configs_updated_ok')); } if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_xml']) && isset($_POST['home_cfg_id'])) { $edit_id = (int)$_POST['home_cfg_id']; $nodesPayload = isset($_POST['nodes']) && is_array($_POST['nodes']) ? $_POST['nodes'] : []; if (config_games_save_xml($db, $edit_id, $nodesPayload)) { print_success(get_lang('configs_updated_ok')); } else { print_failure('Failed to save XML configuration.'); } $_GET['home_cfg_id'] = $edit_id; } $game_cfgs = $db->getGameCfgs(); echo "Use the action dropdown to remove entire sections. Attribute values left blank will be removed. Script sections such as post_install are fully editable.
"; } } } } if(isset($_GET['xml_config_creator'])) { echo ""; } else { echo "