mirror of
https://github.com/ceratic/MediaCollectorLibary.git
synced 2026-05-13 23:56:46 +02:00
- Deleted test scripts: test_jellyfin_execution.php, test_stash.php, test_xbvr.php, test_xbvr_sync.php, vite.config.js - Added DashboardController for fetching dashboard statistics and recent activity - Added GameController for managing games, including fetching all games, game details, and games by category - Introduced various check scripts to validate database structures and data integrity for adult videos, games, gender data, posters, and TV show actors
365 lines
11 KiB
PHP
365 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Api;
|
|
|
|
use Psr\Http\Message\ResponseInterface as Response;
|
|
use Psr\Http\Message\ServerRequestInterface as Request;
|
|
use App\Models\Game;
|
|
use App\Controllers\Api\BaseApiController;
|
|
|
|
class GameController extends BaseApiController
|
|
{
|
|
/**
|
|
* Get all games grouped by completion status
|
|
*/
|
|
public function index(Request $request, Response $response, array $args): Response
|
|
{
|
|
$queryParams = $request->getQueryParams();
|
|
$search = $queryParams['search'] ?? '';
|
|
$sort = $queryParams['sort'] ?? 'title_asc';
|
|
|
|
try {
|
|
// Get games from database
|
|
$games = $this->getAllGamesWithCategories($search, $sort);
|
|
|
|
// Group games by completion status
|
|
$groupedGames = $this->groupGamesByCategory($games);
|
|
|
|
return $this->json($response, [
|
|
'success' => true,
|
|
'data' => $groupedGames
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return $this->json($response, [
|
|
'success' => false,
|
|
'message' => 'Failed to fetch games: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get game by ID
|
|
*/
|
|
public function show(Request $request, Response $response, array $args): Response
|
|
{
|
|
$gameId = $args['id'] ?? null;
|
|
|
|
if (!$gameId) {
|
|
return $this->json($response, [
|
|
'success' => false,
|
|
'message' => 'Game ID is required'
|
|
], 400);
|
|
}
|
|
|
|
try {
|
|
$game = $this->getGameDetails($gameId);
|
|
|
|
if (!$game) {
|
|
return $this->json($response, [
|
|
'success' => false,
|
|
'message' => 'Game not found'
|
|
], 404);
|
|
}
|
|
|
|
return $this->json($response, [
|
|
'success' => true,
|
|
'data' => $game
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return $this->json($response, [
|
|
'success' => false,
|
|
'message' => 'Failed to fetch game: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get games by category (BEATEN, PLAYING, etc.)
|
|
*/
|
|
public function getByCategory(Request $request, Response $response, array $args): Response
|
|
{
|
|
$category = strtoupper($args['category'] ?? '');
|
|
$queryParams = $request->getQueryParams();
|
|
$search = $queryParams['search'] ?? '';
|
|
$sort = $queryParams['sort'] ?? 'title_asc';
|
|
|
|
if (!in_array($category, ['BEATEN', 'PLAYING', 'COMPLETED', 'UNPLAYED'])) {
|
|
return $this->json($response, [
|
|
'success' => false,
|
|
'message' => 'Invalid category. Must be one of: BEATEN, PLAYING, COMPLETED, UNPLAYED'
|
|
], 400);
|
|
}
|
|
|
|
try {
|
|
$games = $this->getGamesByCategory($category, $search, $sort);
|
|
|
|
return $this->json($response, [
|
|
'success' => true,
|
|
'data' => [
|
|
'category' => $category,
|
|
'games' => $games,
|
|
'count' => count($games)
|
|
]
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return $this->json($response, [
|
|
'success' => false,
|
|
'message' => 'Failed to fetch games by category: ' . $e->getMessage()
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get all games from database
|
|
*/
|
|
private function getAllGamesWithCategories(string $search = '', string $sort = 'title_asc'): array
|
|
{
|
|
$pdo = $this->getPdo();
|
|
|
|
$sql = "
|
|
SELECT
|
|
g.id,
|
|
g.title,
|
|
g.poster_url,
|
|
g.backdrop_url,
|
|
g.rating,
|
|
g.release_date,
|
|
g.platform,
|
|
g.developer,
|
|
g.genres,
|
|
g.playtime_hours,
|
|
g.completion_status,
|
|
g.last_played,
|
|
g.community_score,
|
|
g.critic_score,
|
|
g.source_name
|
|
FROM games g
|
|
WHERE 1=1
|
|
";
|
|
|
|
$params = [];
|
|
|
|
// Add search filter
|
|
if (!empty($search)) {
|
|
$sql .= " AND (g.title LIKE :search OR g.developer LIKE :search)";
|
|
$params[':search'] = '%' . $search . '%';
|
|
}
|
|
|
|
// Add sorting
|
|
switch ($sort) {
|
|
case 'title_desc':
|
|
$sql .= " ORDER BY g.title DESC";
|
|
break;
|
|
case 'year_asc':
|
|
$sql .= " ORDER BY g.release_date ASC";
|
|
break;
|
|
case 'year_desc':
|
|
$sql .= " ORDER BY g.release_date DESC";
|
|
break;
|
|
case 'playtime_desc':
|
|
$sql .= " ORDER BY g.playtime_hours DESC";
|
|
break;
|
|
case 'rating_desc':
|
|
$sql .= " ORDER BY g.rating DESC";
|
|
break;
|
|
case 'last_played_desc':
|
|
$sql .= " ORDER BY g.last_played DESC";
|
|
break;
|
|
default:
|
|
$sql .= " ORDER BY g.title ASC";
|
|
}
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
|
|
$games = [];
|
|
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
|
// Parse genres if stored as JSON
|
|
if (!empty($row['genres'])) {
|
|
$genres = json_decode($row['genres'], true);
|
|
$row['genres'] = is_array($genres) ? $genres : [];
|
|
} else {
|
|
$row['genres'] = [];
|
|
}
|
|
|
|
// Set default completion status
|
|
if (empty($row['completion_status'])) {
|
|
$row['completion_status'] = 'UNPLAYED';
|
|
}
|
|
|
|
$games[] = $row;
|
|
}
|
|
|
|
return $games;
|
|
}
|
|
|
|
/**
|
|
* Group games by completion status
|
|
*/
|
|
private function groupGamesByCategory(array $games): array
|
|
{
|
|
$categories = [
|
|
'BEATEN' => ['name' => 'BEATEN', 'count' => 0, 'games' => []],
|
|
'PLAYING' => ['name' => 'PLAYING', 'count' => 0, 'games' => []],
|
|
'COMPLETED' => ['name' => 'COMPLETED', 'count' => 0, 'games' => []],
|
|
'UNPLAYED' => ['name' => 'UNPLAYED', 'count' => 0, 'games' => []]
|
|
];
|
|
|
|
foreach ($games as $game) {
|
|
$status = $game['completion_status'] ?? 'UNPLAYED';
|
|
if (isset($categories[$status])) {
|
|
$categories[$status]['games'][] = $game;
|
|
$categories[$status]['count']++;
|
|
}
|
|
}
|
|
|
|
return array_values($categories);
|
|
}
|
|
|
|
/**
|
|
* Get games by specific category
|
|
*/
|
|
private function getGamesByCategory(string $category, string $search = '', string $sort = 'title_asc'): array
|
|
{
|
|
$pdo = $this->getPdo();
|
|
|
|
$sql = "
|
|
SELECT
|
|
g.id,
|
|
g.title,
|
|
g.poster_url,
|
|
g.backdrop_url,
|
|
g.rating,
|
|
g.release_date,
|
|
g.platform,
|
|
g.developer,
|
|
g.genres,
|
|
g.playtime_hours,
|
|
g.completion_status,
|
|
g.last_played,
|
|
g.community_score,
|
|
g.critic_score,
|
|
g.source_name
|
|
FROM games g
|
|
WHERE g.completion_status = :category
|
|
";
|
|
|
|
$params = [':category' => $category];
|
|
|
|
// Add search filter
|
|
if (!empty($search)) {
|
|
$sql .= " AND (g.title LIKE :search OR g.developer LIKE :search)";
|
|
$params[':search'] = '%' . $search . '%';
|
|
}
|
|
|
|
// Add sorting
|
|
switch ($sort) {
|
|
case 'title_desc':
|
|
$sql .= " ORDER BY g.title DESC";
|
|
break;
|
|
case 'year_asc':
|
|
$sql .= " ORDER BY g.release_date ASC";
|
|
break;
|
|
case 'year_desc':
|
|
$sql .= " ORDER BY g.release_date DESC";
|
|
break;
|
|
case 'playtime_desc':
|
|
$sql .= " ORDER BY g.playtime_hours DESC";
|
|
break;
|
|
case 'rating_desc':
|
|
$sql .= " ORDER BY g.rating DESC";
|
|
break;
|
|
case 'last_played_desc':
|
|
$sql .= " ORDER BY g.last_played DESC";
|
|
break;
|
|
default:
|
|
$sql .= " ORDER BY g.title ASC";
|
|
}
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
|
|
$games = [];
|
|
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
|
// Parse genres if stored as JSON
|
|
if (!empty($row['genres'])) {
|
|
$genres = json_decode($row['genres'], true);
|
|
$row['genres'] = is_array($genres) ? $genres : [];
|
|
} else {
|
|
$row['genres'] = [];
|
|
}
|
|
|
|
$games[] = $row;
|
|
}
|
|
|
|
return $games;
|
|
}
|
|
|
|
/**
|
|
* Get detailed game information
|
|
*/
|
|
private function getGameDetails(int $gameId): ?array
|
|
{
|
|
$pdo = $this->getPdo();
|
|
|
|
$sql = "
|
|
SELECT
|
|
g.id,
|
|
g.title,
|
|
g.poster_url,
|
|
g.backdrop_url,
|
|
g.rating,
|
|
g.release_date,
|
|
g.platform,
|
|
g.developer,
|
|
g.publisher,
|
|
g.genres,
|
|
g.playtime_hours,
|
|
g.completion_status,
|
|
g.last_played,
|
|
g.community_score,
|
|
g.critic_score,
|
|
g.source_name,
|
|
g.description,
|
|
g.gameplay,
|
|
g.synopsis,
|
|
g.age_ratings,
|
|
g.version,
|
|
g.time_to_beat,
|
|
g.controls,
|
|
g.pacing,
|
|
g.perspective,
|
|
g.series
|
|
FROM games g
|
|
WHERE g.id = :id
|
|
";
|
|
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute([':id' => $gameId]);
|
|
|
|
$game = $stmt->fetch(\PDO::FETCH_ASSOC);
|
|
|
|
if (!$game) {
|
|
return null;
|
|
}
|
|
|
|
// Parse JSON fields
|
|
$jsonFields = ['genres', 'age_ratings'];
|
|
foreach ($jsonFields as $field) {
|
|
if (!empty($game[$field])) {
|
|
$decoded = json_decode($game[$field], true);
|
|
$game[$field] = is_array($decoded) ? $decoded : [];
|
|
} else {
|
|
$game[$field] = [];
|
|
}
|
|
}
|
|
|
|
// Set default completion status
|
|
if (empty($game['completion_status'])) {
|
|
$game['completion_status'] = 'UNPLAYED';
|
|
}
|
|
|
|
return $game;
|
|
}
|
|
}
|