Commit workspace changes

This commit is contained in:
2026-04-05 19:42:33 +02:00
parent 148a3bbe43
commit 08ad757bcb
312 changed files with 35149 additions and 399 deletions

View File

@@ -11,6 +11,7 @@ use App\Models\ContentType;
use App\Models\ArtworkVersion;
use App\Services\Cdn\ArtworkCdnPurgeService;
use App\Services\ArtworkSearchIndexer;
use App\Services\ArtworkAttributionService;
use App\Services\TagService;
use App\Services\ArtworkVersioningService;
use App\Services\Studio\StudioArtworkQueryService;
@@ -118,7 +119,7 @@ final class StudioArtworksApiController extends Controller
* PUT /api/studio/artworks/{id}
* Update artwork details (title, description, visibility).
*/
public function update(Request $request, int $id): JsonResponse
public function update(Request $request, int $id, ArtworkAttributionService $attribution): JsonResponse
{
$artwork = $request->user()->artworks()->findOrFail($id);
@@ -138,8 +139,32 @@ final class StudioArtworksApiController extends Controller
'description_source' => 'sometimes|nullable|string|in:manual,ai_generated,ai_applied,mixed',
'tags_source' => 'sometimes|nullable|string|in:manual,ai_generated,ai_applied,mixed',
'category_source' => 'sometimes|nullable|string|in:manual,ai_generated,ai_applied,mixed',
'group' => 'sometimes|nullable|string|max:90',
'primary_author_user_id' => 'sometimes|nullable|integer|min:1',
'contributor_user_ids' => 'sometimes|array|max:20',
'contributor_user_ids.*' => 'integer|min:1',
'contributor_credits' => 'sometimes|array|max:20',
'contributor_credits.*.user_id' => 'required|integer|min:1',
'contributor_credits.*.credit_role' => 'nullable|string|max:80',
'contributor_credits.*.is_primary' => 'nullable|boolean',
]);
$hasAttributionUpdates = array_key_exists('group', $validated)
|| array_key_exists('primary_author_user_id', $validated)
|| array_key_exists('contributor_user_ids', $validated)
|| array_key_exists('contributor_credits', $validated);
$attributionPayload = [
'group' => $validated['group'] ?? $artwork->group?->slug,
'primary_author_user_id' => $validated['primary_author_user_id'] ?? $artwork->primary_author_user_id,
'contributor_user_ids' => $validated['contributor_user_ids'] ?? $artwork->contributors()->pluck('user_id')->all(),
'contributor_credits' => $validated['contributor_credits'] ?? $artwork->contributors()->get()->map(fn ($contributor): array => [
'user_id' => (int) $contributor->user_id,
'credit_role' => $contributor->credit_role,
'is_primary' => (bool) $contributor->is_primary,
])->values()->all(),
];
$visibility = (string) ($validated['visibility'] ?? ($artwork->visibility ?: ((bool) $artwork->is_public ? Artwork::VISIBILITY_PUBLIC : Artwork::VISIBILITY_PRIVATE)));
$mode = (string) ($validated['mode'] ?? ($artwork->artwork_status === 'scheduled' ? 'schedule' : 'now'));
$timezone = array_key_exists('timezone', $validated)
@@ -165,7 +190,7 @@ final class StudioArtworksApiController extends Controller
$tags = $validated['tags'] ?? null;
$categoryId = $validated['category_id'] ?? null;
$contentTypeId = $validated['content_type_id'] ?? null;
unset($validated['tags'], $validated['category_id'], $validated['content_type_id'], $validated['visibility'], $validated['mode'], $validated['publish_at'], $validated['timezone']);
unset($validated['tags'], $validated['category_id'], $validated['content_type_id'], $validated['visibility'], $validated['mode'], $validated['publish_at'], $validated['timezone'], $validated['group'], $validated['primary_author_user_id'], $validated['contributor_user_ids'], $validated['contributor_credits']);
$validated['visibility'] = $visibility;
$validated['artwork_timezone'] = $timezone;
@@ -215,6 +240,10 @@ final class StudioArtworksApiController extends Controller
}
}
if ($hasAttributionUpdates) {
$artwork = $attribution->apply($artwork->fresh(['group.members', 'contributors', 'primaryAuthor.profile']), $request->user(), $attributionPayload);
}
// Reindex in Meilisearch
try {
if ((bool) $artwork->is_public && (bool) $artwork->is_approved && $artwork->published_at) {
@@ -227,7 +256,7 @@ final class StudioArtworksApiController extends Controller
}
// Reload relationships for response
$artwork->load(['categories.contentType', 'tags']);
$artwork->load(['categories.contentType', 'tags', 'group', 'primaryAuthor.profile', 'contributors.user.profile']);
$primaryCategory = $artwork->categories->first();
return response()->json([
@@ -243,6 +272,14 @@ final class StudioArtworksApiController extends Controller
'artwork_status' => $artwork->artwork_status,
'artwork_timezone' => $artwork->artwork_timezone,
'slug' => $artwork->slug,
'group_slug' => $artwork->group?->slug,
'primary_author_user_id' => (int) ($artwork->primary_author_user_id ?: $artwork->user_id),
'contributor_user_ids' => $artwork->contributors->pluck('user_id')->map(fn ($contributorId): int => (int) $contributorId)->values()->all(),
'contributor_credits' => $artwork->contributors->map(fn ($contributor): array => [
'user_id' => (int) $contributor->user_id,
'credit_role' => $contributor->credit_role,
'is_primary' => (bool) $contributor->is_primary,
])->values()->all(),
'content_type_id' => $primaryCategory?->contentType?->id,
'category_id' => $primaryCategory?->id,
'tags' => $artwork->tags->map(fn ($t) => ['id' => $t->id, 'name' => $t->name, 'slug' => $t->slug])->values()->all(),