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; } }