From 9550cd32b4c077660c817d7bed6b59fda47df8fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 May 2026 17:15:07 +0000 Subject: [PATCH] fix: billing order flow, steam_workshop lang key, workshop module install queries - order.php: replace foreach((array)$mysqli_result) with proper fetch_assoc() loop - order.php: fix hidden service_id field to use $_REQUEST instead of $_POST - order.php: add safe error messages and error_log() on failed service lookup - lang/English/global.php: add OGP_LANG_steam_workshop to fix _steam_workshop_ raw key - steam_workshop/module.php: replace unusable $module_db_create heredoc with proper $install_queries[0] array so tables are created during module install - timestamp.txt: updated Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/70fa0082-93ad-4a4d-a1b3-ea6afa77ee80 Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com> --- lang/English/global.php | 1 + modules/billing/order.php | 65 +++++++++-------- modules/billing/timestamp.txt | 2 +- modules/steam_workshop/module.php | 112 +++++++++++++++--------------- 4 files changed, 95 insertions(+), 85 deletions(-) diff --git a/lang/English/global.php b/lang/English/global.php index b8b252fc..cf0b2cfa 100644 --- a/lang/English/global.php +++ b/lang/English/global.php @@ -78,6 +78,7 @@ define('OGP_LANG_xml_file_not_valid', "XML file '%s' could not be validated with define('OGP_LANG_unable_to_load_xml', "Unable to load XML file '%s'. Permission issue?"); define('OGP_LANG_gamemanager', "Game Manager"); define('OGP_LANG_game_monitor', "Game Monitor"); +define('OGP_LANG_steam_workshop', "Steam Workshop"); define('OGP_LANG_dashboard', "Dashboard"); define('OGP_LANG_user_addons', "Addons"); define('OGP_LANG_ftp', "FTP"); diff --git a/modules/billing/order.php b/modules/billing/order.php index d07b02ca..96d86381 100644 --- a/modules/billing/order.php +++ b/modules/billing/order.php @@ -66,39 +66,46 @@ THIS IS WHAT WE DISPLAY ON THE SHOP PAGE AT THE TOP query($qry_services); - - if (isset($_REQUEST['service_id']) && $services === false) { - echo ""; - return; + $req_service_id = intval($_REQUEST['service_id'] ?? 0); + if ($req_service_id !== 0) { + $where_service_id = " WHERE enabled = 1 AND service_id=" . $req_service_id; + } else { + $where_service_id = " WHERE enabled = 1"; } - - foreach ((array)$services as $key => $row) { - $service_ids[$key] = $row['service_id']; - $home_cfg_id[$key] = $row['home_cfg_id']; - $mod_cfg_id[$key] = $row['mod_cfg_id']; - $service_name[$key] = $row['service_name']; - $remote_server_id[$key] = $row['remote_server_id']; - $slot_max_qty[$key] = $row['slot_max_qty']; - $slot_min_qty[$key] = $row['slot_min_qty']; - $price_daily[$key] = $row['price_daily']; - $price_monthly[$key] = $row['price_monthly']; - $price_year[$key] = $row['price_year']; - $description[$key] = $row['description']; - $img_url[$key] = $row['img_url']; - $ftp[$key] = $row['ftp']; - $install_method[$key] = $row['install_method']; - $manual_url[$key] = $row['manual_url']; - $access_rights_list[$key] = $row['access_rights']; + $qry_services = "SELECT * FROM {$table_prefix}billing_services " . $where_service_id . " ORDER BY service_name"; + $services_result = $db->query($qry_services); + + if ($services_result === false) { + echo "

Unable to load service information. Please try again or contact support.

"; + error_log("billing order.php: query failed - " . $db->error . " | SQL: " . $qry_services); + billing_maybe_close_db($db); + include(__DIR__ . '/includes/footer.php'); + echo ''; + exit; } - + + // Fetch all rows into an array so foreach works correctly + $serviceRows = []; + while ($row = $services_result->fetch_assoc()) { + $serviceRows[] = $row; + } + $services_result->free(); + + if ($req_service_id !== 0 && empty($serviceRows)) { + error_log("billing order.php: service_id={$req_service_id} not found or not enabled"); + echo "

The requested service could not be found or is no longer available.

"; + echo "

Back to server list

"; + billing_maybe_close_db($db); + include(__DIR__ . '/includes/footer.php'); + echo ''; + exit; + } + ?>
@@ -177,7 +184,7 @@ if ($row['price_monthly'] == 0.0) {
- + diff --git a/modules/billing/timestamp.txt b/modules/billing/timestamp.txt index c740e878..f498fa7b 100644 --- a/modules/billing/timestamp.txt +++ b/modules/billing/timestamp.txt @@ -1 +1 @@ -Last Updated at 3:21pm on 2026-02-05 +Last Updated at 5:10pm on 2026-05-04 diff --git a/modules/steam_workshop/module.php b/modules/steam_workshop/module.php index 8c6228fa..515557d0 100644 --- a/modules/steam_workshop/module.php +++ b/modules/steam_workshop/module.php @@ -28,60 +28,62 @@ $db_version = 1; $module_required = TRUE; $module_menus = array(); -// Database schema migration: create the three Workshop tables when not present. -// Called by the panel module installer when db_version increments. -$module_db_create = <<<'SQL' -CREATE TABLE IF NOT EXISTS `OGP_DB_PREFIXworkshop_game_profiles` ( - `id` INT NOT NULL AUTO_INCREMENT, - `game_key` VARCHAR(100) NOT NULL, - `game_name` VARCHAR(255) NOT NULL, - `workshop_app_id` VARCHAR(32) NOT NULL, - `supported_os` SET('linux','windows') NOT NULL DEFAULT 'linux', - `cache_path_template` TEXT NOT NULL, - `install_path_template` TEXT NOT NULL, - `folder_name_template` VARCHAR(255) NOT NULL DEFAULT '@{mod_id}', - `copy_method` ENUM('rsync','robocopy','custom_script') NOT NULL DEFAULT 'rsync', - `install_script` TEXT NULL, - `config_file_template` TEXT NULL, - `launch_param_template` TEXT NULL, - `requires_restart` TINYINT(1) NOT NULL DEFAULT 1, - `enabled` TINYINT(1) NOT NULL DEFAULT 1, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_game_key` (`game_key`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +// Database schema: create the three Workshop tables when the module is installed. +// $install_queries[0] is run during initial install (from db_version 0 to 1). +// Each table uses IF NOT EXISTS so re-running is safe. +$install_queries = array(); +$install_queries[0] = array( + "CREATE TABLE IF NOT EXISTS `".OGP_DB_PREFIX."workshop_game_profiles` ( + `id` INT NOT NULL AUTO_INCREMENT, + `game_key` VARCHAR(100) NOT NULL, + `game_name` VARCHAR(255) NOT NULL, + `workshop_app_id` VARCHAR(32) NOT NULL, + `supported_os` SET('linux','windows') NOT NULL DEFAULT 'linux', + `cache_path_template` TEXT NOT NULL, + `install_path_template` TEXT NOT NULL, + `folder_name_template` VARCHAR(255) NOT NULL DEFAULT '@{mod_id}', + `copy_method` ENUM('rsync','robocopy','custom_script') NOT NULL DEFAULT 'rsync', + `install_script` TEXT NULL, + `config_file_template` TEXT NULL, + `launch_param_template` TEXT NULL, + `requires_restart` TINYINT(1) NOT NULL DEFAULT 1, + `enabled` TINYINT(1) NOT NULL DEFAULT 1, + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_game_key` (`game_key`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci", -CREATE TABLE IF NOT EXISTS `OGP_DB_PREFIXworkshop_cache` ( - `id` INT NOT NULL AUTO_INCREMENT, - `agent_id` INT NOT NULL, - `os_type` ENUM('linux','windows') NOT NULL DEFAULT 'linux', - `workshop_app_id` VARCHAR(32) NOT NULL, - `workshop_id` VARCHAR(64) NOT NULL, - `title` VARCHAR(255) NULL, - `cache_path` TEXT NOT NULL, - `status` ENUM('missing','cached','failed') NOT NULL DEFAULT 'missing', - `last_checked` DATETIME NULL, - `last_updated` DATETIME NULL, - `last_error` TEXT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_agent_workshop` (`agent_id`, `workshop_app_id`, `workshop_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + "CREATE TABLE IF NOT EXISTS `".OGP_DB_PREFIX."workshop_cache` ( + `id` INT NOT NULL AUTO_INCREMENT, + `agent_id` INT NOT NULL, + `os_type` ENUM('linux','windows') NOT NULL DEFAULT 'linux', + `workshop_app_id` VARCHAR(32) NOT NULL, + `workshop_id` VARCHAR(64) NOT NULL, + `title` VARCHAR(255) NULL, + `cache_path` TEXT NOT NULL, + `status` ENUM('missing','cached','failed') NOT NULL DEFAULT 'missing', + `last_checked` DATETIME NULL, + `last_updated` DATETIME NULL, + `last_error` TEXT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_agent_workshop` (`agent_id`, `workshop_app_id`, `workshop_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci", -CREATE TABLE IF NOT EXISTS `OGP_DB_PREFIXserver_workshop_mods` ( - `id` INT NOT NULL AUTO_INCREMENT, - `home_id` INT NOT NULL, - `agent_id` INT NOT NULL, - `profile_id` INT NOT NULL, - `workshop_app_id` VARCHAR(32) NOT NULL, - `workshop_id` VARCHAR(64) NOT NULL, - `title` VARCHAR(255) NULL, - `enabled` TINYINT(1) NOT NULL DEFAULT 1, - `install_path` TEXT NOT NULL, - `load_order` INT NOT NULL DEFAULT 0, - `installed_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `uniq_home_workshop` (`home_id`, `workshop_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -SQL; + "CREATE TABLE IF NOT EXISTS `".OGP_DB_PREFIX."server_workshop_mods` ( + `id` INT NOT NULL AUTO_INCREMENT, + `home_id` INT NOT NULL, + `agent_id` INT NOT NULL, + `profile_id` INT NOT NULL, + `workshop_app_id` VARCHAR(32) NOT NULL, + `workshop_id` VARCHAR(64) NOT NULL, + `title` VARCHAR(255) NULL, + `enabled` TINYINT(1) NOT NULL DEFAULT 1, + `install_path` TEXT NOT NULL, + `load_order` INT NOT NULL DEFAULT 0, + `installed_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `uniq_home_workshop` (`home_id`, `workshop_id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci" +);