'date', 'track_count' => 'int', 'total_duration_seconds' => 'int', 'is_favorite' => 'bool' ]; public function source() { $stmt = $this->pdo->prepare("SELECT * FROM sources WHERE id = :source_id"); $stmt->execute(['source_id' => $this->source_id]); $sourceData = $stmt->fetch(\PDO::FETCH_ASSOC); return $sourceData ? new Source($this->pdo, $sourceData) : null; } /** * Get the artist for this album */ public function artist() { $stmt = $this->pdo->prepare("SELECT * FROM music_artists WHERE id = :artist_id"); $stmt->execute(['artist_id' => $this->artist_id]); $artistData = $stmt->fetch(\PDO::FETCH_ASSOC); return $artistData ? new MusicArtist($this->pdo, $artistData) : null; } /** * Get all tracks for this album */ public function tracks() { $stmt = $this->pdo->prepare(" SELECT * FROM music_tracks WHERE album_id = :album_id ORDER BY track_number ASC, title ASC "); $stmt->execute(['album_id' => $this->id]); return $stmt->fetchAll(\PDO::FETCH_ASSOC); } /** * Toggle favorite status */ public function toggleFavorite(): bool { return $this->update($this->id, [ 'is_favorite' => !$this->is_favorite ]); } /** * Get total count of albums with optional filters */ public static function getTotalCount(\PDO $pdo, string $search = '', array $genres = [], array $artists = []): int { $where = []; $params = []; $sql = "SELECT COUNT(*) as count FROM music_albums ma JOIN sources s ON ma.source_id = s.id"; if (!empty($search)) { $where[] = "(ma.title LIKE :search OR ma.artist_name LIKE :search)"; $params[':search'] = "%$search%"; } if (!empty($genres)) { $genreConditions = []; foreach ($genres as $i => $genre) { $param = ":genre_$i"; $genreConditions[] = "ma.genre LIKE $param"; $params[$param] = "%$genre%"; } $where[] = "(" . implode(' OR ', $genreConditions) . ")"; } if (!empty($artists)) { $artistConditions = []; foreach ($artists as $i => $artist) { $param = ":artist_$i"; $artistConditions[] = "ma.artist_name LIKE $param"; $params[$param] = "%$artist%"; } $where[] = "(" . implode(' OR ', $artistConditions) . ")"; } if (!empty($where)) { $sql .= " WHERE " . implode(' AND ', $where); } $stmt = $pdo->prepare($sql); $stmt->execute($params); return (int)$stmt->fetchColumn(); } /** * Get paginated albums with optional filters */ public static function getAllWithPagination( \PDO $pdo, int $page = 1, int $perPage = 20, string $search = '', array $genres = [], array $artists = [], string $sort = 'title_asc' ): array { $offset = ($page - 1) * $perPage; $where = []; $params = []; if (!empty($search)) { $where[] = "(title LIKE :search OR artist_name LIKE :search)"; $params[':search'] = "%$search%"; } if (!empty($genres)) { $genreConditions = []; foreach ($genres as $i => $genre) { $param = ":genre$i"; $genreConditions[] = "genre LIKE $param"; $params[$param] = "%$genre%"; } $where[] = "(" . implode(' OR ', $genreConditions) . ")"; } if (!empty($artists)) { $artistConditions = []; foreach ($artists as $i => $artist) { $param = ":artist$i"; $artistConditions[] = "artist_name LIKE $param"; $params[$param] = "%$artist%"; } $where[] = "(" . implode(' OR ', $artistConditions) . ")"; } // Determine sort order $orderBy = 'title ASC'; switch ($sort) { case 'title_desc': $orderBy = 'title DESC'; break; case 'artist_asc': $orderBy = 'artist_name ASC'; break; case 'artist_desc': $orderBy = 'artist_name DESC'; break; case 'release_asc': $orderBy = 'release_date ASC'; break; case 'release_desc': $orderBy = 'release_date DESC'; break; } $sql = "SELECT ma.*, s.display_name as source_name FROM music_albums ma JOIN sources s ON ma.source_id = s.id"; if (!empty($where)) { $sql .= " WHERE " . implode(' AND ', $where); } $sql .= " ORDER BY $orderBy LIMIT :limit OFFSET :offset"; $stmt = $pdo->prepare($sql); // Bind parameters foreach ($params as $key => $value) { $stmt->bindValue($key, $value); } $stmt->bindValue(':limit', $perPage, \PDO::PARAM_INT); $stmt->bindValue(':offset', $offset, \PDO::PARAM_INT); $stmt->execute(); return $stmt->fetchAll(\PDO::FETCH_ASSOC); } /** * Get all unique genres from albums */ public static function getAvailableGenres(\PDO $pdo): array { $stmt = $pdo->query("SELECT DISTINCT genre FROM music_albums WHERE genre IS NOT NULL AND genre != '' ORDER BY genre"); return $stmt->fetchAll(\PDO::FETCH_COLUMN); } /** * Get all unique artists from albums */ public static function getAvailableArtists(\PDO $pdo): array { $stmt = $pdo->query("SELECT DISTINCT artist_name FROM music_albums WHERE artist_name IS NOT NULL AND artist_name != '' ORDER BY artist_name"); return $stmt->fetchAll(\PDO::FETCH_COLUMN); } /** * Get album statistics */ public static function getStats(\PDO $pdo): array { $stmt = $pdo->query(" SELECT COUNT(*) as total_albums, COUNT(CASE WHEN is_favorite = 1 THEN 1 END) as favorite_albums, SUM(track_count) as total_tracks, SUM(total_duration_seconds) as total_duration FROM music_albums "); return $stmt->fetch(\PDO::FETCH_ASSOC); } }