Move neighbor lookup into a dedicated service and let the viewer load adjacent artworks after first paint instead of blocking the detail request.
71 lines
2.2 KiB
PHP
71 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Artwork;
|
|
use Illuminate\Support\Str;
|
|
|
|
final class ArtworkNavigationService
|
|
{
|
|
/**
|
|
* Build the public previous/next navigation payload for an already loaded
|
|
* current artwork. No current-artwork lookup is performed here.
|
|
*/
|
|
public function navigationFor(Artwork $artwork): array
|
|
{
|
|
$scope = Artwork::published()
|
|
->select(['id', 'title', 'slug', 'hash', 'file_path', 'file_name'])
|
|
->where('user_id', $artwork->user_id);
|
|
|
|
$prev = (clone $scope)->where('id', '<', $artwork->id)->orderByDesc('id')->first();
|
|
$next = (clone $scope)->where('id', '>', $artwork->id)->orderBy('id')->first();
|
|
|
|
if (! $prev) {
|
|
$prev = (clone $scope)->where('id', '!=', $artwork->id)->orderByDesc('id')->first();
|
|
}
|
|
if (! $next) {
|
|
$next = (clone $scope)->where('id', '!=', $artwork->id)->orderBy('id')->first();
|
|
}
|
|
|
|
$prevSlug = $this->canonicalSlug($prev);
|
|
$nextSlug = $this->canonicalSlug($next);
|
|
|
|
return [
|
|
'prev_id' => $prev?->id,
|
|
'next_id' => $next?->id,
|
|
'prev_url' => $prev ? url('/art/'.$prev->id.'/'.$prevSlug) : null,
|
|
'next_url' => $next ? url('/art/'.$next->id.'/'.$nextSlug) : null,
|
|
'prev_slug' => $prevSlug,
|
|
'next_slug' => $nextSlug,
|
|
'prev_preview' => $this->preview($prev),
|
|
'next_preview' => $this->preview($next),
|
|
];
|
|
}
|
|
|
|
private function canonicalSlug(?Artwork $artwork): ?string
|
|
{
|
|
if (! $artwork) {
|
|
return null;
|
|
}
|
|
|
|
return Str::slug($artwork->slug ?: $artwork->title) ?: (string) $artwork->id;
|
|
}
|
|
|
|
private function preview(?Artwork $artwork): ?array
|
|
{
|
|
if (! $artwork) {
|
|
return null;
|
|
}
|
|
|
|
return [
|
|
'id' => (int) $artwork->id,
|
|
'title' => (string) $artwork->title,
|
|
'slug' => (string) $artwork->slug,
|
|
'thumbs' => [
|
|
'md' => ThumbnailPresenter::present($artwork, 'md'),
|
|
'lg' => ThumbnailPresenter::present($artwork, 'lg'),
|
|
],
|
|
];
|
|
}
|
|
}
|