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:
parent
199b398543
commit
69f415ad86
10 changed files with 1334 additions and 312 deletions
|
|
@ -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
|
||||
// ------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -157,24 +157,58 @@ class WorkshopProfileController
|
|||
$osValues = array_values(array_intersect($osRaw, $allowedOs));
|
||||
$supportedOs = implode(',', $osValues !== [] ? $osValues : ['linux']);
|
||||
|
||||
$allowedMethods = ['rsync', 'robocopy', 'custom_script'];
|
||||
$copyMethod = in_array($post['copy_method'] ?? '', $allowedMethods, true)
|
||||
$allowedCopyMethods = ['copy', 'rsync', 'symlink'];
|
||||
$copyMethod = in_array($post['copy_method'] ?? '', $allowedCopyMethods, true)
|
||||
? (string)$post['copy_method']
|
||||
: 'rsync';
|
||||
|
||||
$allowedLoginModes = ['anonymous', 'account'];
|
||||
$steamcmdLoginMode = in_array($post['steamcmd_login_mode'] ?? '', $allowedLoginModes, true)
|
||||
? (string)$post['steamcmd_login_mode']
|
||||
: 'anonymous';
|
||||
|
||||
$allowedFolderFormats = ['@%mod_name%', '@%workshop_id%', 'custom'];
|
||||
$folderNamingFormat = in_array($post['folder_naming_format'] ?? '', $allowedFolderFormats, true)
|
||||
? (string)$post['folder_naming_format']
|
||||
: '@%workshop_id%';
|
||||
|
||||
$allowedSeparators = ['semicolon', 'comma', 'space'];
|
||||
$modSeparator = in_array($post['mod_separator'] ?? '', $allowedSeparators, true)
|
||||
? (string)$post['mod_separator']
|
||||
: 'semicolon';
|
||||
|
||||
// When folder naming is preset (@%mod_name% or @%workshop_id%), derive template from format.
|
||||
// When 'custom', use the admin-supplied value.
|
||||
$folderNameTemplate = $folderNamingFormat !== 'custom'
|
||||
? $folderNamingFormat
|
||||
: trim((string)($post['folder_name_template'] ?? '@%workshop_id%'));
|
||||
|
||||
return [
|
||||
'game_key' => trim((string)($post['game_key'] ?? '')),
|
||||
'game_name' => trim((string)($post['game_name'] ?? '')),
|
||||
'steam_app_id' => preg_replace('/[^0-9]/', '', (string)($post['steam_app_id'] ?? '')) ?? '',
|
||||
'workshop_app_id' => preg_replace('/[^0-9]/', '', (string)($post['workshop_app_id'] ?? '')) ?? '',
|
||||
'steam_login_required' => !empty($post['steam_login_required']) ? 1 : 0,
|
||||
'steamcmd_login_mode' => $steamcmdLoginMode,
|
||||
'steamcmd_path' => trim((string)($post['steamcmd_path'] ?? '')),
|
||||
'supported_os' => $supportedOs,
|
||||
'cache_path_template' => trim((string)($post['cache_path_template'] ?? '')),
|
||||
'install_path_template' => trim((string)($post['install_path_template'] ?? '')),
|
||||
'folder_name_template' => trim((string)($post['folder_name_template'] ?? '@{mod_id}')),
|
||||
'folder_naming_format' => $folderNamingFormat,
|
||||
'folder_name_template' => $folderNameTemplate,
|
||||
'mod_launch_param' => trim((string)($post['mod_launch_param'] ?? '')),
|
||||
'mod_separator' => $modSeparator,
|
||||
'copy_method' => $copyMethod,
|
||||
'copy_keys' => !empty($post['copy_keys']) ? 1 : 0,
|
||||
'key_source_path' => trim((string)($post['key_source_path'] ?? '')),
|
||||
'key_dest_path' => trim((string)($post['key_dest_path'] ?? '')),
|
||||
'pre_update_script' => trim((string)($post['pre_update_script'] ?? '')),
|
||||
'install_script' => trim((string)($post['install_script'] ?? '')),
|
||||
'post_update_script' => trim((string)($post['post_update_script'] ?? '')),
|
||||
'config_file_template' => trim((string)($post['config_file_template'] ?? '')),
|
||||
'launch_param_template' => trim((string)($post['launch_param_template'] ?? '')),
|
||||
'requires_restart' => !empty($post['requires_restart']) ? 1 : 0,
|
||||
'validation_notes' => trim((string)($post['validation_notes'] ?? '')),
|
||||
'enabled' => !empty($post['enabled']) ? 1 : 0,
|
||||
];
|
||||
}
|
||||
|
|
@ -198,10 +232,13 @@ class WorkshopProfileController
|
|||
$errors[] = $this->lang['error_app_id_required'] ?? 'Workshop App ID is required.';
|
||||
}
|
||||
if (($data['cache_path_template'] ?? '') === '') {
|
||||
$errors[] = $this->lang['error_cache_path_required'] ?? 'Cache path template is required.';
|
||||
$errors[] = $this->lang['error_cache_path_required'] ?? 'SteamCMD cache path template is required.';
|
||||
}
|
||||
if (($data['install_path_template'] ?? '') === '') {
|
||||
$errors[] = $this->lang['error_install_path_required'] ?? 'Install path template is required.';
|
||||
$errors[] = $this->lang['error_install_path_required'] ?? 'Server install path template is required.';
|
||||
}
|
||||
if (($data['folder_naming_format'] ?? '') === 'custom' && ($data['folder_name_template'] ?? '') === '') {
|
||||
$errors[] = $this->lang['error_folder_template_required'] ?? 'Custom folder name template is required when format is set to custom.';
|
||||
}
|
||||
return $errors;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue