pdo = $pdo; } public function index(Request $request, Response $response, $args) { $queryParams = $request->getQueryParams(); // Get pagination parameters $page = max(1, (int)($queryParams['page'] ?? 1)); $perPage = max(12, min(100, (int)($queryParams['per_page'] ?? 24))); // Get search parameters $search = trim($queryParams['search'] ?? ''); // Get filter parameters $genres = $queryParams['genres'] ?? []; if (!is_array($genres)) { $genres = [$genres]; } $genres = array_filter($genres); $artists = $queryParams['artists'] ?? []; if (!is_array($artists)) { $artists = [$artists]; } $artists = array_filter($artists); // Get view mode $viewMode = $queryParams['view'] ?? 'grid'; // grid, list, covers // Get sort parameter $sort = $queryParams['sort'] ?? 'title_asc'; // Get albums with pagination, filters, and sorting $albums = \App\Models\MusicAlbum::getAllWithPagination($this->pdo, $page, $perPage, $search, $genres, $artists, $sort); // Get total count for pagination $totalCount = \App\Models\MusicAlbum::getTotalCount($this->pdo, $search, $genres, $artists); // Get available filter options $availableGenres = \App\Models\MusicAlbum::getAvailableGenres($this->pdo); $availableArtists = \App\Models\MusicAlbum::getAvailableArtists($this->pdo); // Calculate pagination info $totalPages = ceil($totalCount / $perPage); $hasNextPage = $page < $totalPages; $hasPrevPage = $page > 1; return $this->view->render($response, 'music/index.twig', [ 'title' => 'Music', 'albums' => $albums, 'pagination' => [ 'current_page' => $page, 'per_page' => $perPage, 'total_pages' => $totalPages, 'total_items' => $totalCount, 'has_next' => $hasNextPage, 'has_prev' => $hasPrevPage, 'next_page' => $page + 1, 'prev_page' => $page - 1 ], 'search' => $search, 'view_mode' => $viewMode, 'view_modes' => ['grid', 'list', 'covers'], 'filters' => [ 'genres' => $genres, 'artists' => $artists ], 'available_filters' => [ 'genres' => $availableGenres, 'artists' => $availableArtists ], 'sort' => $sort, 'sort_options' => [ 'title_asc' => 'Title (A-Z)', 'title_desc' => 'Title (Z-A)', 'artist_asc' => 'Artist (A-Z)', 'artist_desc' => 'Artist (Z-A)', 'release_desc' => 'Release Date (Newest First)', 'release_asc' => 'Release Date (Oldest First)', 'added_desc' => 'Recently Added', 'added_asc' => 'Oldest Added' ] ]); } public function show(Request $request, Response $response, $args) { $albumId = (int) $args['id']; // Get album details $stmt = $this->pdo->prepare(" SELECT ma.*, s.display_name as source_name FROM music_albums ma JOIN sources s ON ma.source_id = s.id WHERE ma.id = :id "); $stmt->execute(['id' => $albumId]); $album = $stmt->fetch(\PDO::FETCH_ASSOC); if (!$album) { return $response->withStatus(404); } // Decode metadata for display $metadata = json_decode($album['metadata'], true); // Get tracks for this album $stmt = $this->pdo->prepare(" SELECT mt.* FROM music_tracks mt WHERE mt.album_id = :album_id ORDER BY mt.track_number ASC, mt.title ASC "); $stmt->execute(['album_id' => $albumId]); $tracks = $stmt->fetchAll(\PDO::FETCH_ASSOC); // Get artist information $artist = null; if ($album['artist_id']) { $stmt = $this->pdo->prepare(" SELECT ma.*, s.display_name as source_name FROM music_artists ma JOIN sources s ON ma.source_id = s.id WHERE ma.id = :artist_id "); $stmt->execute(['artist_id' => $album['artist_id']]); $artist = $stmt->fetch(\PDO::FETCH_ASSOC); } return $this->view->render($response, 'music/show.twig', [ 'title' => $album['title'], 'album' => $album, 'tracks' => $tracks, 'artist' => $artist, 'metadata' => $metadata ]); } }