Files
MediaCollectorLibary/app/Controllers/AdminController.php
Lars Behrends 73d8441787 i dont know
2025-10-20 23:40:55 +02:00

206 lines
6.8 KiB
PHP

<?php
namespace App\Controllers;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use App\Models\Source;
use App\Models\SyncLog;
use App\Services\SteamSyncService;
use App\Services\JellyfinSyncService;
use App\Services\StashSyncService;
use App\Services\XbvrSyncService;
use App\Services\AdultSyncService;
use App\Services\ExophaseSyncService;
use PDO;
use Slim\Views\Twig;
class AdminController extends AdminBaseController
{
protected PDO $pdo;
public function __construct(PDO $pdo, Twig $view)
{
parent::__construct($pdo, $view);
$this->pdo = $pdo;
}
public function index(Request $request, Response $response, $args)
{
$sourceModel = new Source($this->pdo);
$sources = $sourceModel->findAll();
$syncLogModel = new SyncLog($this->pdo);
$recentSyncs = SyncLog::getRecent($this->pdo, 10);
return $this->render($response, 'admin/index.twig', [
'title' => 'Admin Dashboard',
'sources' => $sources,
'recent_syncs' => $recentSyncs
]);
}
public function syncSource(Request $request, Response $response, $args)
{
$sourceId = $args['id'];
$syncType = $request->getQueryParams()['type'] ?? 'full';
$sourceModel = new Source($this->pdo);
$source = $sourceModel->find($sourceId);
if (!$source) {
return $response->withStatus(404)->withHeader('Content-Type', 'application/json');
}
// Validate sync type based on source type
if ($source['name'] === 'jellyfin') {
$validSyncTypes = ['full', 'incremental', 'all', 'movies', 'tvshows', 'cleanup'];
if (!in_array($syncType, $validSyncTypes)) {
return $this->json($response, [
'success' => false,
'message' => 'Invalid sync type for Jellyfin source. Valid types: ' . implode(', ', $validSyncTypes)
], 400);
}
} else {
// For other sources, only allow full/incremental
$validSyncTypes = ['full', 'incremental'];
if (!in_array($syncType, $validSyncTypes)) {
return $this->json($response, [
'success' => false,
'message' => 'Invalid sync type. Valid types: ' . implode(', ', $validSyncTypes)
], 400);
}
}
// Start sync in background (simplified - in production you'd use queues)
$syncLogId = $this->startSync($source, $syncType);
return $this->json($response, [
'success' => true,
'sync_log_id' => $syncLogId,
'message' => 'Sync started successfully'
]);
}
public function syncStatus(Request $request, Response $response, $args)
{
$syncLogId = $args['id'];
$syncLogModel = new SyncLog($this->pdo);
$syncLog = $syncLogModel->find($syncLogId);
if (!$syncLog) {
return $response->withStatus(404)->withHeader('Content-Type', 'application/json');
}
return $this->json($response, [
'id' => $syncLog['id'],
'status' => $syncLog['status'],
'sync_type' => $syncLog['sync_type'],
'total_items' => $syncLog['total_items'] ?? 0,
'processed_items' => $syncLog['processed_items'],
'new_items' => $syncLog['new_items'],
'updated_items' => $syncLog['updated_items'],
'deleted_items' => $syncLog['deleted_items'],
'started_at' => $syncLog['started_at'],
'completed_at' => $syncLog['completed_at'],
'message' => $syncLog['message'],
'errors' => $syncLog['errors'] ? json_decode($syncLog['errors'], true) : [],
'progress_percentage' => $this->calculateProgressPercentage($syncLog)
]);
}
private function calculateProgressPercentage(array $syncLog): float
{
$total = $syncLog['total_items'] ?? 0;
if ($total <= 0) return 0;
$processed = $syncLog['processed_items'] ?? 0;
return min(100, round(($processed / $total) * 100, 2));
}
public function settings(Request $request, Response $response, $args)
{
return $this->render($response, 'admin/settings.twig', [
'title' => 'Admin Settings',
'current_route' => 'settings'
]);
}
public function sources(Request $request, Response $response, $args)
{
$sourceModel = new Source($this->pdo);
$sources = $sourceModel->findAll();
return $this->render($response, 'admin/sources.twig', [
'title' => 'Source Management',
'sources' => $sources,
'current_route' => 'sources'
]);
}
private function startSync(array $source, string $syncType): int
{
// Create sync log entry first
$syncLogId = $this->createSyncLog($source, $syncType);
// Start sync in background process
$this->startBackgroundSync($source['id'], $syncType, $syncLogId);
return $syncLogId;
}
private function createSyncLog(array $source, string $syncType): int
{
$data = [
'source_id' => $source['id'],
'sync_type' => $syncType,
'status' => 'started',
'total_items' => 0,
'processed_items' => 0,
'new_items' => 0,
'updated_items' => 0,
'deleted_items' => 0,
'started_at' => date('Y-m-d H:i:s')
];
$columns = array_keys($data);
$placeholders = array_map(fn($col) => ":$col", $columns);
$sql = "INSERT INTO sync_logs (" . implode(', ', $columns) . ") VALUES (" . implode(', ', $placeholders) . ")";
$stmt = $this->pdo->prepare($sql);
$stmt->execute($data);
return (int) $this->pdo->lastInsertId();
}
private function startBackgroundSync(int $sourceId, string $syncType, int $syncLogId): void
{
$scriptPath = __DIR__ . '/../../sync-runner.php';
$command = sprintf(
'php %s %d %s %d > /dev/null 2>&1 &',
escapeshellarg($scriptPath),
$sourceId,
escapeshellarg($syncType),
$syncLogId
);
// Execute the command in background
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// Windows
pclose(popen('start /B ' . $command, 'r'));
} else {
// Unix-like systems
exec($command);
}
// */
// Update sync log to indicate it's running (this will be updated again by the script)
$syncLogModel = new SyncLog($this->pdo);
$syncLogModel->update($syncLogId, [
'status' => 'running',
'message' => 'Sync process starting in background'
]);
}
}