mirror of
https://github.com/ceratic/MediaCollectorLibary.git
synced 2026-05-13 23:56:46 +02:00
739 lines
25 KiB
PHP
739 lines
25 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
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Media Management
|
|
*/
|
|
|
|
// Movies Management
|
|
public function movies(Request $request, Response $response, $args)
|
|
{
|
|
$movieModel = new \App\Models\Movie($this->pdo);
|
|
|
|
// Get query parameters with defaults
|
|
$page = max(1, (int)($request->getQueryParams()['page'] ?? 1));
|
|
$search = trim($request->getQueryParams()['search'] ?? '');
|
|
$genre = trim($request->getQueryParams()['genre'] ?? '');
|
|
$director = trim($request->getQueryParams()['director'] ?? '');
|
|
$sort = trim($request->getQueryParams()['sort'] ?? 'title_asc');
|
|
$perPage = 20;
|
|
|
|
// Prepare filters for the view
|
|
$filters = [
|
|
'search' => $search,
|
|
'genre' => $genre,
|
|
'director' => $director,
|
|
'sort' => $sort
|
|
];
|
|
|
|
// Get paginated and filtered movies
|
|
$movies = $movieModel->getPaginated(
|
|
$this->pdo,
|
|
$page,
|
|
$perPage,
|
|
$search,
|
|
$genre ? [$genre] : [],
|
|
$sort
|
|
);
|
|
|
|
// Get available genres and directors for filters
|
|
$genres = $movieModel->getGenres($this->pdo);
|
|
$directors = $movieModel->getDirectors($this->pdo);
|
|
|
|
// Calculate pagination data
|
|
$totalMovies = $movieModel->getTotalCount(
|
|
$this->pdo,
|
|
$search,
|
|
$genre ? [$genre] : []
|
|
);
|
|
|
|
$totalPages = max(1, ceil($totalMovies / $perPage));
|
|
$currentPage = min($page, $totalPages);
|
|
|
|
// Get flash messages if any
|
|
// $successMessages = $this->container->get('flash')->getMessage('success');
|
|
|
|
return $this->render($response, 'admin/movies/index.twig', [
|
|
'title' => 'Manage Movies',
|
|
'movies' => $movies,
|
|
'genres' => $genres,
|
|
'directors' => $directors,
|
|
'filters' => $filters,
|
|
'pagination' => [
|
|
'current' => $currentPage,
|
|
'total' => $totalPages,
|
|
'per_page' => $perPage,
|
|
'total_items' => $totalMovies,
|
|
'from' => (($currentPage - 1) * $perPage) + 1,
|
|
'to' => min($currentPage * $perPage, $totalMovies)
|
|
]
|
|
|
|
]);
|
|
}
|
|
|
|
public function editMovie(Request $request, Response $response, $args)
|
|
{
|
|
$id = $args['id'] ?? null;
|
|
$movieModel = new \App\Models\Movie($this->pdo);
|
|
|
|
if ($request->getMethod() === 'POST') {
|
|
$data = $request->getParsedBody();
|
|
|
|
if ($id) {
|
|
// Update existing movie
|
|
$movieModel->update($id, $data);
|
|
//$this->flash->addMessage('success', 'Movie updated successfully');
|
|
} else {
|
|
// Create new movie
|
|
$id = $movieModel->create($data);
|
|
// $this->flash->addMessage('success', 'Movie created successfully');
|
|
}
|
|
|
|
return $response->withHeader('Location', '/admin/movies/' . $id . '/edit')
|
|
->withStatus(302);
|
|
}
|
|
|
|
$movie = $id ? $movieModel->find($id) : null;
|
|
|
|
return $this->render($response, 'admin/movies/edit.twig', [
|
|
'title' => $id ? 'Edit Movie' : 'Add New Movie',
|
|
'movie' => $movie
|
|
]);
|
|
}
|
|
|
|
public function deleteMovie(Request $request, Response $response, $args)
|
|
{
|
|
$id = $args['id'];
|
|
$movieModel = new \App\Models\Movie($this->pdo);
|
|
$movieModel->delete($id);
|
|
|
|
$this->flash->addMessage('success', 'Movie deleted successfully');
|
|
return $response->withHeader('Location', '/admin/movies')
|
|
->withStatus(302);
|
|
}
|
|
|
|
// Games Management
|
|
public function games(Request $request, Response $response, $args)
|
|
{
|
|
$gameModel = new \App\Models\Game($this->pdo);
|
|
|
|
// Get query parameters
|
|
$page = (int)($request->getQueryParams()['page'] ?? 1);
|
|
$search = $request->getQueryParams()['search'] ?? '';
|
|
$platform = $request->getQueryParams()['platform'] ?? '';
|
|
$genre = $request->getQueryParams()['genre'] ?? '';
|
|
$isInstalled = $request->getQueryParams()['installed'] ?? '';
|
|
$isFavorite = $request->getQueryParams()['favorite'] ?? '';
|
|
$sort = $request->getQueryParams()['sort'] ?? 'title_asc';
|
|
$perPage = 20; // Items per page
|
|
|
|
// Prepare filters
|
|
$filters = [
|
|
'search' => $search,
|
|
'platform' => $platform,
|
|
'genre' => $genre,
|
|
'is_installed' => $isInstalled,
|
|
'is_favorite' => $isFavorite,
|
|
'sort' => $sort
|
|
];
|
|
|
|
// Get paginated and filtered games
|
|
$result = $gameModel->getGroupedGamesWithPagination(
|
|
$this->pdo,
|
|
$page,
|
|
$perPage,
|
|
$search,
|
|
$genre ? [$genre] : [],
|
|
$platform ? [$platform] : []
|
|
);
|
|
|
|
// Get available platforms and genres for filters
|
|
$platforms = $gameModel->getPlatforms();
|
|
$genres = $gameModel->getGenres();
|
|
|
|
// Calculate pagination data
|
|
$totalGames = $gameModel->getTotalCount(
|
|
$this->pdo,
|
|
$search,
|
|
$genre ? [$genre] : [],
|
|
$platform ? [$platform] : []
|
|
);
|
|
|
|
$totalPages = ceil($totalGames / $perPage);
|
|
|
|
return $this->render($response, 'admin/games/index.twig', [
|
|
'title' => 'Manage Games',
|
|
'games' => $result,
|
|
'platforms' => $platforms,
|
|
'genres' => $genres,
|
|
'filters' => $filters,
|
|
'pagination' => [
|
|
'current' => $page,
|
|
'total' => $totalPages,
|
|
'per_page' => $perPage,
|
|
'total_items' => $totalGames
|
|
]
|
|
]);
|
|
}
|
|
|
|
public function editGame(Request $request, Response $response, $args)
|
|
{
|
|
$id = $args['id'] ?? null;
|
|
$gameModel = new \App\Models\Game($this->pdo);
|
|
|
|
if ($request->getMethod() === 'POST') {
|
|
$data = $request->getParsedBody();
|
|
|
|
if ($id) {
|
|
$gameModel->update($id, $data);
|
|
} else {
|
|
$id = $gameModel->create($data);
|
|
}
|
|
|
|
return $response->withHeader('Location', '/admin/games/' . $id . '/edit')
|
|
->withStatus(302);
|
|
}
|
|
|
|
$game = $id ? $gameModel->find($id) : null;
|
|
|
|
return $this->render($response, 'admin/games/edit.twig', [
|
|
'title' => $id ? 'Edit Game' : 'Add New Game',
|
|
'game' => $game
|
|
]);
|
|
}
|
|
|
|
public function deleteGame(Request $request, Response $response, $args)
|
|
{
|
|
$id = $args['id'];
|
|
$gameModel = new \App\Models\Game($this->pdo);
|
|
$gameModel->delete($id);
|
|
|
|
return $response->withHeader('Location', '/admin/games')
|
|
->withStatus(302);
|
|
}
|
|
|
|
// TV Shows Management
|
|
public function shows(Request $request, Response $response, $args)
|
|
{
|
|
$showModel = new \App\Models\TvShow($this->pdo);
|
|
|
|
// Get query parameters with defaults
|
|
$page = max(1, (int)($request->getQueryParams()['page'] ?? 1));
|
|
$search = trim($request->getQueryParams()['search'] ?? '');
|
|
$genre = trim($request->getQueryParams()['genre'] ?? '');
|
|
$network = trim($request->getQueryParams()['network'] ?? '');
|
|
$status = trim($request->getQueryParams()['status'] ?? '');
|
|
$sort = trim($request->getQueryParams()['sort'] ?? 'name_asc');
|
|
$perPage = 20;
|
|
|
|
// Prepare filters for the view
|
|
$filters = [
|
|
'search' => $search,
|
|
'genre' => $genre,
|
|
'network' => $network,
|
|
'status' => $status,
|
|
'sort' => $sort
|
|
];
|
|
|
|
// Get paginated and filtered shows
|
|
$shows = $showModel->getPaginated(
|
|
$this->pdo,
|
|
$page,
|
|
$perPage,
|
|
$search,
|
|
$genre ? [$genre] : [],
|
|
$network ? [$network] : [],
|
|
$status ? [$status] : [],
|
|
$sort
|
|
);
|
|
|
|
// Get available filters
|
|
$genres = $showModel->getGenres($this->pdo);
|
|
//$networks = $showModel->getNetworks($this->pdo);
|
|
$statuses = ['Returning Series', 'Ended', 'Canceled', 'In Production'];
|
|
|
|
// Calculate pagination data
|
|
$totalShows = $showModel->getTotalCount(
|
|
$this->pdo,
|
|
$search,
|
|
$genre ? [$genre] : [],
|
|
$network ? [$network] : [],
|
|
$status ? [$status] : []
|
|
);
|
|
|
|
$totalPages = max(1, ceil($totalShows / $perPage));
|
|
$currentPage = min($page, $totalPages);
|
|
|
|
return $this->render($response, 'admin/shows/index.twig', [
|
|
'title' => 'Manage TV Shows',
|
|
'shows' => $shows,
|
|
'genres' => $genres,
|
|
//'networks' => $networks,
|
|
'statuses' => $statuses,
|
|
'filters' => $filters,
|
|
'pagination' => [
|
|
'current' => $currentPage,
|
|
'total' => $totalPages,
|
|
'per_page' => $perPage,
|
|
'total_items' => $totalShows,
|
|
'from' => (($currentPage - 1) * $perPage) + 1,
|
|
'to' => min($currentPage * $perPage, $totalShows)
|
|
]
|
|
]);
|
|
}
|
|
|
|
public function editShow(Request $request, Response $response, $args)
|
|
{
|
|
$id = $args['id'] ?? null;
|
|
$showModel = new \App\Models\TvShow($this->pdo);
|
|
|
|
if ($request->getMethod() === 'POST') {
|
|
$data = $request->getParsedBody();
|
|
|
|
if ($id) {
|
|
$showModel->update($id, $data);
|
|
} else {
|
|
$id = $showModel->create($data);
|
|
}
|
|
|
|
return $response->withHeader('Location', '/admin/shows/' . $id . '/edit')
|
|
->withStatus(302);
|
|
}
|
|
|
|
$show = $id ? $showModel->find($id) : null;
|
|
|
|
return $this->render($response, 'admin/shows/edit.twig', [
|
|
'title' => $id ? 'Edit TV Show' : 'Add New TV Show',
|
|
'show' => $show
|
|
]);
|
|
}
|
|
|
|
public function deleteShow(Request $request, Response $response, $args)
|
|
{
|
|
$id = $args['id'];
|
|
$showModel = new \App\Models\TvShow($this->pdo);
|
|
$showModel->delete($id);
|
|
|
|
return $response->withHeader('Location', '/admin/shows')
|
|
->withStatus(302);
|
|
}
|
|
|
|
/**
|
|
* Display a listing of adult videos with pagination and filters
|
|
*/
|
|
public function adultVideos(Request $request, Response $response, $args)
|
|
{
|
|
$adultVideoModel = new \App\Models\AdultVideo($this->pdo);
|
|
|
|
// Get query parameters with defaults
|
|
$page = max(1, (int)($request->getQueryParams()['page'] ?? 1));
|
|
$search = trim($request->getQueryParams()['search'] ?? '');
|
|
$genre = trim($request->getQueryParams()['genre'] ?? '');
|
|
$director = trim($request->getQueryParams()['director'] ?? '');
|
|
$sort = trim($request->getQueryParams()['sort'] ?? 'newest');
|
|
$perPage = 20;
|
|
|
|
// Prepare filters for the view
|
|
$filters = [
|
|
'search' => $search,
|
|
'genre' => $genre,
|
|
'director' => $director,
|
|
'sort' => $sort
|
|
];
|
|
|
|
// Get available filters
|
|
$genres = $adultVideoModel::getAvailableGenres($this->pdo);
|
|
$directors = $adultVideoModel::getAvailableDirectors($this->pdo);
|
|
|
|
// Get paginated and filtered adult videos
|
|
$videos = $adultVideoModel::getAllWithPagination(
|
|
$this->pdo,
|
|
$page,
|
|
$perPage,
|
|
$search,
|
|
$genre ? [$genre] : [],
|
|
$director ? [$director] : []
|
|
);
|
|
|
|
// Get total count for pagination
|
|
$totalVideos = $adultVideoModel::getTotalCount(
|
|
$this->pdo,
|
|
$search,
|
|
$genre ? [$genre] : [],
|
|
$director ? [$director] : []
|
|
);
|
|
|
|
$totalPages = max(1, ceil($totalVideos / $perPage));
|
|
$currentPage = min($page, $totalPages);
|
|
|
|
return $this->render($response, 'admin/adult/index.twig', [
|
|
'title' => 'Manage Adult Videos',
|
|
'videos' => $videos,
|
|
'genres' => $genres,
|
|
'directors' => $directors,
|
|
'filters' => $filters,
|
|
'pagination' => [
|
|
'current' => $currentPage,
|
|
'total' => $totalPages,
|
|
'per_page' => $perPage,
|
|
'total_items' => $totalVideos,
|
|
'from' => (($currentPage - 1) * $perPage) + 1,
|
|
'to' => min($currentPage * $perPage, $totalVideos)
|
|
]
|
|
]);
|
|
}
|
|
|
|
public function editAdultVideo(Request $request, Response $response, $args)
|
|
{
|
|
$id = $args['id'] ?? null;
|
|
$adultModel = new \App\Models\AdultVideo($this->pdo);
|
|
|
|
if ($request->getMethod() === 'POST') {
|
|
$data = $request->getParsedBody();
|
|
|
|
if ($id) {
|
|
$adultModel->update($id, $data);
|
|
} else {
|
|
$id = $adultModel->create($data);
|
|
}
|
|
|
|
return $response->withHeader('Location', '/admin/adult/' . $id . '/edit')
|
|
->withStatus(302);
|
|
}
|
|
|
|
$video = $id ? $adultModel->find($id) : null;
|
|
|
|
return $this->render($response, 'admin/adult/edit.twig', [
|
|
'title' => $id ? 'Edit Adult Video' : 'Add New Adult Video',
|
|
'video' => $video
|
|
]);
|
|
}
|
|
|
|
public function deleteAdultVideo(Request $request, Response $response, $args)
|
|
{
|
|
$id = $args['id'];
|
|
$adultModel = new \App\Models\AdultVideo($this->pdo);
|
|
$adultModel->delete($id);
|
|
|
|
return $response->withHeader('Location', '/admin/adult')
|
|
->withStatus(302);
|
|
}
|
|
|
|
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'
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Get actors for a specific adult video
|
|
*/
|
|
public function getAdultVideoActors(Request $request, Response $response, $args)
|
|
{
|
|
$adultVideo = new \App\Models\AdultVideo($this->pdo);
|
|
$video = $adultVideo->find($args['id']);
|
|
|
|
if (!$video) {
|
|
$response->getBody()->write(json_encode(['error' => 'Video not found']));
|
|
return $response->withStatus(404)->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
$actors = $adultVideo->actors($args['id']);
|
|
$response->getBody()->write(json_encode(['data' => $actors]));
|
|
return $response->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
/**
|
|
* Add an actor to an adult video
|
|
*/
|
|
public function addActorToAdultVideo(Request $request, Response $response, $args)
|
|
{
|
|
$contentType = $request->getHeaderLine('Content-Type');
|
|
|
|
if (strstr($contentType, 'application/json')) {
|
|
$data = json_decode((string)$request->getBody(), true);
|
|
} else {
|
|
$data = $request->getParsedBody();
|
|
}
|
|
|
|
$actorId = $data['actor_id'] ?? null;
|
|
|
|
if (!$actorId) {
|
|
$response->getBody()->write(json_encode(['error' => 'Actor ID is required']));
|
|
return $response->withStatus(400)->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
$adultVideo = new \App\Models\AdultVideo($this->pdo);
|
|
$video = $adultVideo->find($args['id']);
|
|
|
|
if (!$video) {
|
|
$response->getBody()->write(json_encode(['error' => 'Video not found']));
|
|
return $response->withStatus(404)->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
$success = $adultVideo->addActor($actorId);
|
|
|
|
if ($success) {
|
|
$adultVideo->updateCastField();
|
|
$response->getBody()->write(json_encode([
|
|
'success' => true,
|
|
'message' => 'Actor added successfully'
|
|
]));
|
|
return $response->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
$response->getBody()->write(json_encode(['error' => 'Failed to add actor']));
|
|
return $response->withStatus(500)->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
/**
|
|
* Remove an actor from an adult video
|
|
*/
|
|
public function removeActorFromAdultVideo(Request $request, Response $response, $args)
|
|
{
|
|
$actorId = $args['actorId'] ?? null;
|
|
|
|
if (!$actorId) {
|
|
$response->getBody()->write(json_encode(['error' => 'Actor ID is required']));
|
|
return $response->withStatus(400)->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
$adultVideo = new \App\Models\AdultVideo($this->pdo);
|
|
$video = $adultVideo->find($args['id']);
|
|
|
|
if (!$video) {
|
|
$response->getBody()->write(json_encode(['error' => 'Video not found']));
|
|
return $response->withStatus(404)->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
$success = $adultVideo->removeActor($actorId);
|
|
|
|
if ($success) {
|
|
$adultVideo->updateCastField();
|
|
$response->getBody()->write(json_encode([
|
|
'success' => true,
|
|
'message' => 'Actor removed successfully'
|
|
]));
|
|
return $response->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
$response->getBody()->write(json_encode(['error' => 'Failed to remove actor']));
|
|
return $response->withStatus(500)->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
/**
|
|
* Search actors by name
|
|
*/
|
|
public function searchActors(Request $request, Response $response, $args)
|
|
{
|
|
$query = $request->getQueryParams()['q'] ?? '';
|
|
|
|
if (empty($query)) {
|
|
$response->getBody()->write(json_encode(['data' => []]));
|
|
return $response->withHeader('Content-Type', 'application/json');
|
|
}
|
|
|
|
$adultVideo = new \App\Models\AdultVideo($this->pdo);
|
|
$actors = $adultVideo->searchActors($this->pdo, $query);
|
|
|
|
$response->getBody()->write(json_encode(['data' => $actors]));
|
|
return $response->withHeader('Content-Type', 'application/json');
|
|
}
|
|
}
|