feat: ship creator journey v2 and profile updates

This commit is contained in:
2026-04-12 21:42:07 +02:00
parent a2457f4e49
commit d5cff21ea2
335 changed files with 20147 additions and 1545 deletions

View File

@@ -6,12 +6,17 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\ArtworkIndexRequest;
use App\Models\Artwork;
use App\Models\Category;
use App\Models\ContentType;
use App\Services\ContentTypes\ContentTypeSlugResolver;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
class ArtworkController extends Controller
{
public function __construct(private readonly ContentTypeSlugResolver $contentTypeResolver)
{
}
/**
* Browse artworks with optional category filtering.
* Uses cursor pagination (no offset pagination) and only returns public, approved, not-deleted items.
@@ -58,6 +63,17 @@ class ArtworkController extends Controller
*/
public function show(Request $request, string $contentTypeSlug, string $categoryPath, $artwork = null)
{
$resolution = $this->contentTypeResolver->resolve($contentTypeSlug);
if (! $resolution->found() || $resolution->contentType === null) {
abort(404);
}
$resolvedContentTypeSlug = strtolower((string) $resolution->contentType->slug);
if ($resolution->requiresRedirect()) {
return $this->redirectToCanonicalArtworkPath($request, $resolvedContentTypeSlug, $categoryPath, $artwork, 301);
}
// Manually resolve artwork by slug when provided. The route may bind
// the 'artwork' parameter to an Artwork model or pass the slug string.
$foundArtwork = null;
@@ -67,7 +83,7 @@ class ArtworkController extends Controller
$artworkSlug = $artwork->slug;
} elseif ($artwork) {
$artworkSlug = (string) $artwork;
$foundArtwork = $this->findArtworkForCategoryPath($contentTypeSlug, $categoryPath, $artworkSlug);
$foundArtwork = $this->findArtworkForCategoryPath($resolvedContentTypeSlug, $categoryPath, $artworkSlug);
}
// When the URL can represent a nested category path (e.g. /skins/audio/winamp),
@@ -75,9 +91,9 @@ class ArtworkController extends Controller
// behave consistently.
if (! empty($artworkSlug)) {
$combinedPath = trim($categoryPath . '/' . $artworkSlug, '/');
$resolvedCategory = Category::findByPath($contentTypeSlug, $combinedPath);
$resolvedCategory = Category::findByPath($resolvedContentTypeSlug, $combinedPath);
if ($resolvedCategory) {
return app(BrowseGalleryController::class)->content(request(), $contentTypeSlug, $combinedPath);
return app(BrowseGalleryController::class)->content(request(), $resolvedContentTypeSlug, $combinedPath);
}
}
@@ -90,7 +106,7 @@ class ArtworkController extends Controller
if ($artworkSlug) {
$combinedPath = trim($categoryPath . '/' . $artworkSlug, '/');
}
return app(BrowseGalleryController::class)->content(request(), $contentTypeSlug, $combinedPath);
return app(BrowseGalleryController::class)->content(request(), $resolvedContentTypeSlug, $combinedPath);
}
if (! $foundArtwork->is_public || ! $foundArtwork->is_approved || $foundArtwork->trashed()) {
@@ -108,9 +124,8 @@ class ArtworkController extends Controller
private function findArtworkForCategoryPath(string $contentTypeSlug, string $categoryPath, string $artworkSlug): ?Artwork
{
$contentType = ContentType::query()->where('slug', strtolower($contentTypeSlug))->first();
$segments = array_values(array_filter(explode('/', trim($categoryPath, '/'))));
$category = $contentType ? Category::findByPath($contentType->slug, $segments) : null;
$category = Category::findByPath(strtolower($contentTypeSlug), $segments);
$query = Artwork::query()->where('slug', $artworkSlug);
@@ -125,4 +140,17 @@ class ArtworkController extends Controller
->orderByDesc('id')
->first();
}
private function redirectToCanonicalArtworkPath(Request $request, string $contentTypeSlug, string $categoryPath, Artwork|string|null $artwork, int $status = 301): RedirectResponse
{
$artworkSlug = $artwork instanceof Artwork ? $artwork->slug : (string) $artwork;
$target = url('/' . trim($contentTypeSlug . '/' . trim($categoryPath, '/') . '/' . trim($artworkSlug, '/'), '/'));
$queryString = $request->getQueryString();
if ($queryString) {
$target .= '?' . $queryString;
}
return redirect()->to($target, $status);
}
}