feat(steam_workshop): production rewrite with full admin profile page and server settings

- module.php: bump db_version to 2; full v2 schema in install_queries[0]; ALTER TABLE migration in install_queries[2] adding 11 new profile columns plus server_workshop_settings table
- WorkshopRepository: expand saveProfile() with all new fields (steam_app_id, steamcmd_login_mode, steamcmd_path, mod_separator, copy_keys, key paths, pre/post scripts, validation_notes); add nullOrStr helper; add server settings CRUD (getServerSettings, saveServerSettings, recordUpdateResult, setUpdateQueued, listQueuedUpdateHomes); update insertOrUpdateMod with custom_folder; update listAllEnabledMods to select new columns
- WorkshopProfileController: full extractProfileData() with all new fields; validateProfileData with folder template check
- views/admin/profile_form.php: full rewrite – all required fields (steam_app_id, workshop_app_id, login mode, SteamCMD path, OS, cache path, install path, folder naming dropdown, launch params, mod separator, copy method, copy keys with JS show/hide, key paths, pre/per-mod/post bash scripts with DayZ example, validation notes, config file template)
- views/admin/profiles.php: updated list view columns (App IDs, Login, Method)
- WorkshopInstaller.php: full rewrite with %var% template support (+ legacy {var} compat); buildTemplateVars() resolves all 14 variables; pre/post script execution; triggerSteamCmdDownload uses new profile fields; copyKeys helper
- WorkshopModController: add save_settings and queue_update POST actions; handleModsPage loads serverSettings + allProfiles
- views/user_workshop_mods.php: full rewrite – server settings form (enable, profile selector, update mode, restart behavior), update status grid (status/error/time/success time), queue update button, mod table with custom_folder column and toggle/order auto-submit
- lang/en_US.php: ~80 new string keys for all v2 fields
- steam_workshop.css: new v2 styles (3-col grid, script textarea, status grid, server settings card, badges)"

Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/e7f0d80d-f775-4794-adbd-cf48b55bc9c1

Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-05-04 19:49:36 +00:00 committed by GitHub
parent 199b398543
commit 69f415ad86
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 1334 additions and 312 deletions

View file

@ -72,6 +72,12 @@ class WorkshopModController
case 'sync':
$this->handleSync($userId, $isAdmin);
return;
case 'save_settings':
$this->handleSaveSettings($userId, $isAdmin);
return;
case 'queue_update':
$this->handleQueueUpdate($userId, $isAdmin);
return;
}
}
@ -131,23 +137,40 @@ class WorkshopModController
}
$agentId = (int)($home['remote_server_id'] ?? 0);
$appId = $this->searchService->getSteamAppIdForGameKey((string)($home['game_key'] ?? ''));
$profile = $appId !== null ? $this->repo->getProfileByAppId($appId) : null;
$installedMods = $this->repo->listModsForHome($homeId);
$availableMods = ($profile !== null && $appId !== null)
// Load server-level settings
$serverSettings = $this->repo->getServerSettings($homeId);
// Determine active profile: from server settings, or fall back to app-id lookup
$profile = null;
if ($serverSettings !== null && !empty($serverSettings['profile_id'])) {
$profile = $this->repo->getProfileById((int)$serverSettings['profile_id']);
}
if ($profile === null) {
$appId = $this->searchService->getSteamAppIdForGameKey((string)($home['game_key'] ?? ''));
$profile = $appId !== null ? $this->repo->getProfileByAppId($appId) : null;
}
$appId = $profile !== null ? (string)($profile['workshop_app_id'] ?? '') : null;
// All enabled profiles for the profile selector
$allProfiles = $this->repo->listProfiles(true);
$installedMods = $this->repo->listModsForHome($homeId);
$availableMods = ($profile !== null && $appId !== null)
? $this->repo->listCacheForAgent($agentId, $appId)
: [];
$this->render('user_workshop_mods', [
'lang' => $this->lang,
'home' => $home,
'homeId' => $homeId,
'profile' => $profile,
'appId' => $appId,
'installedMods' => $installedMods,
'availableMods' => $availableMods,
'isAdmin' => $isAdmin,
'lang' => $this->lang,
'home' => $home,
'homeId' => $homeId,
'profile' => $profile,
'appId' => $appId,
'installedMods' => $installedMods,
'availableMods' => $availableMods,
'serverSettings' => $serverSettings ?? [],
'allProfiles' => $allProfiles,
'isAdmin' => $isAdmin,
]);
}
@ -348,6 +371,56 @@ class WorkshopModController
echo json_encode(['ok' => true, 'results' => $payload['results'], 'pagination' => $payload['pagination']]);
}
private function handleSaveSettings(int $userId, bool $isAdmin): void
{
$homeId = (int)($_POST['home_id'] ?? 0);
if ($homeId <= 0) {
print_failure($this->lang['error_missing_home'] ?? 'Select a server first.');
$this->handleIndex($userId, $isAdmin);
return;
}
$home = $this->getHome($homeId, $userId, $isAdmin);
if ($home === null) {
print_failure($this->lang['error_home_not_found'] ?? 'Server not found.');
$this->handleIndex($userId, $isAdmin);
return;
}
$this->repo->saveServerSettings($homeId, [
'workshop_enabled' => !empty($_POST['workshop_enabled']) ? 1 : 0,
'profile_id' => (int)($_POST['profile_id'] ?? 0),
'update_mode' => $_POST['update_mode'] ?? 'manual',
'restart_behavior' => $_POST['restart_behavior'] ?? 'none',
]);
print_success($this->lang['settings_saved'] ?? 'Workshop settings saved.');
$_GET['home_id'] = $homeId;
$this->handleModsPage($userId, $isAdmin);
}
private function handleQueueUpdate(int $userId, bool $isAdmin): void
{
$homeId = (int)($_POST['home_id'] ?? 0);
if ($homeId <= 0) {
print_failure($this->lang['error_missing_home'] ?? 'Select a server first.');
$this->handleIndex($userId, $isAdmin);
return;
}
$home = $this->getHome($homeId, $userId, $isAdmin);
if ($home === null) {
print_failure($this->lang['error_home_not_found'] ?? 'Server not found.');
$this->handleIndex($userId, $isAdmin);
return;
}
$this->repo->setUpdateQueued($homeId, true);
print_success($this->lang['update_queued'] ?? 'Manual update queued. It will run on the next scheduler cycle.');
$_GET['home_id'] = $homeId;
$this->handleModsPage($userId, $isAdmin);
}
// ------------------------------------------------------------------
// Helpers
// ------------------------------------------------------------------