Allow artworks to have one primary category and extra secondaries.

Keep artwork_category as membership, store a deterministic primary_category_id, and let upload plus studio pick up to five additional same-type categories without changing canonical URLs.
This commit is contained in:
test
2026-09-20 14:50:12 +02:00
parent 4d60a876af
commit 232880e01f
43 changed files with 2896 additions and 565 deletions
+16 -4
View File
@@ -861,6 +861,14 @@ class CollectionService
? $collections
: new EloquentCollection(is_array($collections) ? $collections : iterator_to_array($collections));
// The profile producer already eager-loads these relations. Keep the
// mapper safe for direct callers as well, so the card loop never
// triggers relation lazy-loading one collection at a time.
$collectionList->loadMissing([
'user:id,username,name',
'coverArtwork:id,user_id,title,slug,hash,thumb_ext,published_at,is_public,is_approved,deleted_at',
]);
$collectionIds = $collectionList->pluck('id')->map(static fn ($id) => (int) $id)->all();
$hideMatureCovers = ! $ownerView && $this->viewerShouldHideMature($viewer);
@@ -879,12 +887,16 @@ class CollectionService
->all()
: [];
return $collectionList->map(function (Collection $collection) use ($ownerView, $viewer, $firstArtworkMap, $savedCollectionIds) {
return $collectionList->map(function (Collection $collection) use ($ownerView, $viewer, $firstArtworkMap, $savedCollectionIds, $hideMatureCovers) {
// Manual collections have their explicit cover eager-loaded. The
// already bulk-loaded first artwork map is the exact fallback
// used by resolvedCoverArtwork() when that cover is absent or not
// visible, so no per-card relation query is needed here.
$resolvedCover = $collection->isSmart()
? $this->smartCollections->firstArtwork($collection, $ownerView)
: $collection->resolvedCoverArtwork(! $ownerView, ! $ownerView && $this->viewerShouldHideMature($viewer));
: ($collection->relationLoaded('coverArtwork') ? $collection->coverArtwork : null);
$fallbackCover = $firstArtworkMap->get((int) $collection->id);
$cover = $this->eligibleCoverArtwork($resolvedCover, ! $ownerView, ! $ownerView && $this->viewerShouldHideMature($viewer))
$cover = $this->eligibleCoverArtwork($resolvedCover, ! $ownerView, $hideMatureCovers)
? $resolvedCover
: $fallbackCover;
$summary = $collection->summary ?? $collection->description;
@@ -1264,7 +1276,7 @@ class CollectionService
private function mapArtworkPayload(Artwork $artwork, array $extra = []): array
{
$category = $artwork->categories->first();
$category = $artwork->resolvedPrimaryCategory();
$contentType = $category?->contentType;
$stats = $artwork->stats;