Agent-Logs-Url: https://github.com/GameServerPanel/GSP/sessions/b402e67e-690f-4d0c-be37-181af3833298 Co-authored-by: iaretechnician <2749183+iaretechnician@users.noreply.github.com>
247 lines
8.4 KiB
PHP
247 lines
8.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../lib/SteamWorkshopService.php';
|
|
|
|
class AdminWorkshopController
|
|
{
|
|
private SteamWorkshopService $service;
|
|
private array $lang;
|
|
private ?array $adapterFormOverride = null;
|
|
private ?string $adapterFormGameKey = null;
|
|
private array $gameGroups = [];
|
|
|
|
public function __construct(OGPDatabase $db)
|
|
{
|
|
$this->service = new SteamWorkshopService($db);
|
|
$this->lang = $this->loadLang();
|
|
}
|
|
|
|
public function handle(): void
|
|
{
|
|
global $db;
|
|
|
|
$userId = (int)($_SESSION['user_id'] ?? 0);
|
|
if (!$db->isAdmin($userId)) {
|
|
print_failure($this->lang['error_admin_only'] ?? 'Admin access required.');
|
|
return;
|
|
}
|
|
|
|
echo '<link rel="stylesheet" type="text/css" href="modules/steam_workshop/steam_workshop.css" />';
|
|
|
|
$this->gameGroups = $this->service->listWorkshopGameGroups();
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$this->processPost();
|
|
}
|
|
|
|
$mappings = $this->service->getAdapterMappings();
|
|
$adapters = $this->service->loadAdapters();
|
|
$adapterOptions = $this->service->getAdapterOptions();
|
|
$gameRows = $this->buildGameRows($mappings);
|
|
$requestedGame = $this->sanitizeGameKeyInput($_GET['adapter_game'] ?? '');
|
|
$activeGame = $this->adapterFormGameKey !== null ? $this->adapterFormGameKey : $requestedGame;
|
|
|
|
$this->render('admin/index', [
|
|
'lang' => $this->lang,
|
|
'mappings' => $mappings,
|
|
'adapters' => $adapters,
|
|
'adapterOptions' => $adapterOptions,
|
|
'gameRows' => $gameRows,
|
|
'activeGameKey' => $activeGame,
|
|
]);
|
|
}
|
|
|
|
private function processPost(): void
|
|
{
|
|
$action = $_POST['admin_action'] ?? 'save_mappings';
|
|
switch ($action) {
|
|
case 'save_adapter':
|
|
$this->processAdapterSave();
|
|
break;
|
|
case 'delete_adapter':
|
|
$this->processAdapterDelete();
|
|
break;
|
|
case 'save_mappings':
|
|
default:
|
|
$this->processSaveMappings();
|
|
break;
|
|
}
|
|
}
|
|
|
|
private function processSaveMappings(): void
|
|
{
|
|
$payload = $_POST['mapping'] ?? [];
|
|
if (!is_array($payload)) {
|
|
$payload = [];
|
|
}
|
|
|
|
$fanOut = [];
|
|
$groupIndex = $this->indexGameGroups();
|
|
foreach ((array)$payload as $groupKey => $adapterKey) {
|
|
$groupKey = (string)$groupKey;
|
|
$adapterKey = (string)$adapterKey;
|
|
if (!isset($groupIndex[$groupKey])) {
|
|
continue;
|
|
}
|
|
|
|
foreach ((array)$groupIndex[$groupKey] as $gameKey) {
|
|
$fanOut[$gameKey] = $adapterKey;
|
|
}
|
|
}
|
|
|
|
$this->service->saveAdapterMappings($fanOut);
|
|
print_success($this->lang['message_mappings_saved'] ?? 'Adapter mappings saved.');
|
|
}
|
|
|
|
private function processAdapterSave(): void
|
|
{
|
|
$gameKey = $this->sanitizeGameKeyInput($_POST['game_key'] ?? '');
|
|
if ($gameKey === '') {
|
|
print_failure($this->lang['error_game_key_required'] ?? 'Game key required.');
|
|
return;
|
|
}
|
|
|
|
$payload = $_POST['adapter'] ?? [];
|
|
if (!is_array($payload)) {
|
|
$payload = [];
|
|
}
|
|
|
|
try {
|
|
$this->service->saveGameAdapter($gameKey, $payload);
|
|
$this->propagateAdapterMapping($gameKey);
|
|
print_success($this->lang['message_adapter_saved'] ?? 'Adapter saved.');
|
|
$this->adapterFormOverride = null;
|
|
$this->adapterFormGameKey = null;
|
|
} catch (RuntimeException $e) {
|
|
$this->adapterFormGameKey = $gameKey;
|
|
$this->adapterFormOverride = [
|
|
'name' => trim((string)($payload['name'] ?? '')),
|
|
'steam_app_id' => trim((string)($payload['steam_app_id'] ?? '')),
|
|
'mods_dir' => trim((string)($payload['mods_dir'] ?? '')),
|
|
'keys_dir' => trim((string)($payload['keys_dir'] ?? '')),
|
|
'supports_hot_reload' => !empty($payload['supports_hot_reload']),
|
|
'activation_template' => trim((string)($payload['activation_template'] ?? '')),
|
|
'notes' => trim((string)($payload['notes'] ?? '')),
|
|
];
|
|
print_failure($e->getMessage());
|
|
}
|
|
}
|
|
|
|
private function processAdapterDelete(): void
|
|
{
|
|
$gameKey = $this->sanitizeGameKeyInput($_POST['game_key'] ?? '');
|
|
if ($gameKey === '') {
|
|
print_failure($this->lang['error_game_key_required'] ?? 'Game key required.');
|
|
return;
|
|
}
|
|
|
|
if ($this->service->deleteGameAdapter($gameKey)) {
|
|
$this->clearGroupMappings($gameKey);
|
|
print_success($this->lang['message_adapter_deleted'] ?? 'Adapter deleted.');
|
|
} else {
|
|
print_failure($this->lang['error_adapter_delete_failed'] ?? 'Unable to delete adapter.');
|
|
}
|
|
}
|
|
|
|
private function buildGameRows(array $mappings): array
|
|
{
|
|
$rows = [];
|
|
foreach ($this->gameGroups as $group) {
|
|
$primaryKey = isset($group['primary_game_key']) ? (string)$group['primary_game_key'] : '';
|
|
$override = ($primaryKey !== '' && $this->adapterFormGameKey === $primaryKey) ? $this->adapterFormOverride : null;
|
|
|
|
$mappingValues = [];
|
|
foreach ((array)$group['game_keys'] as $gameKey) {
|
|
if (isset($mappings[$gameKey]) && $mappings[$gameKey] !== '') {
|
|
$mappingValues[$mappings[$gameKey]] = true;
|
|
}
|
|
}
|
|
|
|
$rows[] = [
|
|
'group_key' => $group['group_key'] ?? '',
|
|
'app_id' => $group['app_id'] ?? '',
|
|
'game_name' => $group['game_name'] ?? '',
|
|
'game_keys' => $group['game_keys'] ?? [],
|
|
'primary_game_key' => $primaryKey,
|
|
'mixed_mapping' => count((array)$mappingValues) > 1,
|
|
'selected_adapter' => count((array)$mappingValues) === 1 ? array_key_first($mappingValues) : '',
|
|
'exists' => $primaryKey !== '' && $this->service->gameAdapterExists($primaryKey),
|
|
'adapter' => $primaryKey !== '' ? $this->service->getGameAdapter($primaryKey) : null,
|
|
'updated_at' => $primaryKey !== '' ? $this->service->getGameAdapterUpdatedAt($primaryKey) : null,
|
|
'form' => $this->service->getAdapterFormData($primaryKey, $override),
|
|
];
|
|
}
|
|
|
|
return $rows;
|
|
}
|
|
|
|
private function indexGameGroups(): array
|
|
{
|
|
$index = [];
|
|
foreach ($this->gameGroups as $group) {
|
|
$index[$group['group_key']] = $group['game_keys'];
|
|
}
|
|
|
|
return $index;
|
|
}
|
|
|
|
private function propagateAdapterMapping(string $primaryGameKey): void
|
|
{
|
|
foreach ($this->gameGroups as $group) {
|
|
if (!in_array($primaryGameKey, $group['game_keys'], true)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ((array)$group['game_keys'] as $gameKey) {
|
|
$this->service->upsertAdapterMapping($gameKey, $primaryGameKey);
|
|
}
|
|
return;
|
|
}
|
|
|
|
$this->service->upsertAdapterMapping($primaryGameKey, $primaryGameKey);
|
|
}
|
|
|
|
private function clearGroupMappings(string $primaryGameKey): void
|
|
{
|
|
foreach ($this->gameGroups as $group) {
|
|
if (!in_array($primaryGameKey, $group['game_keys'], true)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ((array)$group['game_keys'] as $gameKey) {
|
|
$this->service->removeAdapterMapping($gameKey, $primaryGameKey);
|
|
}
|
|
return;
|
|
}
|
|
|
|
$this->service->removeAdapterMapping($primaryGameKey, $primaryGameKey);
|
|
}
|
|
|
|
private function sanitizeGameKeyInput($value): string
|
|
{
|
|
$gameKey = strtolower(trim((string)$value));
|
|
$sanitized = preg_replace('/[^a-z0-9_\-.]/', '', $gameKey);
|
|
return is_string($sanitized) ? $sanitized : '';
|
|
}
|
|
|
|
private function render(string $view, array $data = []): void
|
|
{
|
|
extract($data);
|
|
$lang = $this->lang;
|
|
require __DIR__ . '/../views/' . $view . '.php';
|
|
}
|
|
|
|
private function loadLang(): array
|
|
{
|
|
$langFile = __DIR__ . '/../lang/en_US.php';
|
|
if (is_file($langFile)) {
|
|
$strings = require $langFile;
|
|
if (is_array($strings)) {
|
|
return $strings;
|
|
}
|
|
}
|
|
|
|
return [];
|
|
}
|
|
}
|