Configured swagger-php for documentation at /docs, probably needs a refactor lol; paginated searchAlbums to fix limit bug with null filters.

This commit is contained in:
boris committed 2026-02-27 20:15:57 +00:00
1 parent 56dea097d6
commit c1b1c2f372
19 files changed
+840 -273

No files matched your search

+100 -37
View File
@@ -146,57 +146,120 @@ class AlbumSearchService
*/
private function fetchExternalPayloads(AlbumSearchCriteria $criteria, string $externalQuery): array
{
$result = $this->lastFmClient->searchAlbums($externalQuery, $criteria->limit);
$searchItems = (array) ($result['albums']['items'] ?? []);
$perPage = max($criteria->limit, 10);
$maxPages = 5;
$seenSearchIds = [];
$persistableIds = [];
$persistableLookup = [];
$pagesScanned = 0;
$this->logger->info('Album search results received', [
for ($page = 1; $page <= $maxPages && count($persistableIds) < $criteria->limit; $page++) {
$pagesScanned++;
$result = $this->lastFmClient->searchAlbums($externalQuery, $perPage, $page);
$searchItems = (array) ($result['albums']['items'] ?? []);
if ($searchItems === []) {
break;
}
$ids = $this->extractExternalIds($searchItems);
$ids = array_values(array_filter($ids, function (string $id) use (&$seenSearchIds): bool {
if ($id === '' || isset($seenSearchIds[$id])) {
return false;
}
$seenSearchIds[$id] = true;
return true;
}));
if ($ids === []) {
continue;
}
$full = $this->lastFmClient->getAlbums($ids);
$albumsPayload = is_array($full) ? ((array) ($full['albums'] ?? [])) : [];
if ($albumsPayload === []) {
continue;
}
$genresByAlbum = $this->tagResolver->resolveGenresForAlbums($albumsPayload);
foreach ($albumsPayload as $payload) {
$albumId = (string) ($payload['id'] ?? '');
if ($albumId === '' || !$this->isIngestableExternalAlbum((array) $payload)) {
continue;
}
$this->albumRepository->upsertFromExternalAlbum(
(array) $payload,
$genresByAlbum[$albumId] ?? []
);
if (!isset($persistableLookup[$albumId])) {
$persistableLookup[$albumId] = true;
$persistableIds[] = $albumId;
}
}
}
$this->logger->info('External album ingestion candidate resolution complete', [
'query' => $externalQuery,
'items' => count($searchItems),
'requested_limit' => $criteria->limit,
'persistable_found' => count($persistableIds),
'pages_scanned' => $pagesScanned,
]);
if ($searchItems === []) {
if ($persistableIds === []) {
return ['payloads' => [], 'stats' => [], 'savedIds' => []];
}
$ids = $this->extractExternalIds($searchItems);
if ($ids === []) {
return ['payloads' => [], 'stats' => [], 'savedIds' => []];
}
$full = $this->lastFmClient->getAlbums($ids);
$albumsPayload = is_array($full) ? ((array) ($full['albums'] ?? [])) : [];
if ($albumsPayload === []) {
$albumsPayload = $searchItems;
}
$genresByAlbum = $this->tagResolver->resolveGenresForAlbums($albumsPayload);
foreach ($albumsPayload as $payload) {
$albumId = (string) ($payload['id'] ?? '');
$this->albumRepository->upsertFromExternalAlbum(
(array) $payload,
$albumId !== '' ? ($genresByAlbum[$albumId] ?? []) : []
);
}
$this->entityManager->flush();
$existing = $this->albumRepository->findByExternalIdsKeyed($ids);
$payloads = [];
foreach ($ids as $externalId) {
$existing = $this->albumRepository->findByExternalIdsKeyed($persistableIds);
$orderedIds = [];
foreach ($persistableIds as $externalId) {
if (isset($existing[$externalId])) {
$payloads[] = $existing[$externalId]->toTemplateArray();
$orderedIds[] = $externalId;
}
if (count($orderedIds) >= $criteria->limit) {
break;
}
}
$payloads = [];
foreach ($orderedIds as $externalId) {
$payloads[] = $existing[$externalId]->toTemplateArray();
}
$payloads = $this->hydrateExternalImages($payloads);
return [
'payloads' => $payloads,
'stats' => $this->reviewRepository->getAggregatesForAlbumIds($ids),
'savedIds' => array_keys($existing),
'stats' => $this->reviewRepository->getAggregatesForAlbumIds($orderedIds),
'savedIds' => $orderedIds,
];
}
/**
* @param array<string,mixed> $payload
*/
private function isIngestableExternalAlbum(array $payload): bool
{
$releaseDate = trim((string) ($payload['release_date'] ?? ''));
if ($releaseDate === '') {
return false;
}
$tracks = $payload['tracks']['items'] ?? null;
if (!is_array($tracks) || $tracks === []) {
return false;
}
foreach ($tracks as $track) {
$name = trim((string) ($track['name'] ?? ''));
if ($name !== '') {
return true;
}
}
return false;
}
/**
* @return array{payloads:array<int,array<mixed>>,stats:array<string,array{count:int,avg:float}>}
*/
@@ -221,7 +284,7 @@ class AlbumSearchService
return [
'payloads' => array_map(static fn(Album $album) => $album->toTemplateArray(), $userAlbums),
'stats' => $this->mapUserStatsToLocalIds($userAlbums, $userStats),
'stats' => $this->mapUserStatsToAlbumIds($userAlbums, $userStats),
];
}
@@ -230,14 +293,14 @@ class AlbumSearchService
* @param array<int,array{count:int,avg:float}> $userStats
* @return array<string,array{count:int,avg:float}>
*/
private function mapUserStatsToLocalIds(array $userAlbums, array $userStats): array
private function mapUserStatsToAlbumIds(array $userAlbums, array $userStats): array
{
$mapped = [];
foreach ($userAlbums as $album) {
$entityId = (int) $album->getId();
$localId = (string) $album->getLocalId();
if ($localId !== '' && isset($userStats[$entityId])) {
$mapped[$localId] = $userStats[$entityId];
$albumId = (string) $album->getExternalId();
if ($albumId !== '' && isset($userStats[$entityId])) {
$mapped[$albumId] = $userStats[$entityId];
}
}