199 lines
8.1 KiB
PHP
199 lines
8.1 KiB
PHP
<?php
|
|
namespace App\Http\Resources;
|
|
|
|
use App\Services\ContentSanitizer;
|
|
use App\Services\ThumbnailPresenter;
|
|
use Illuminate\Http\Resources\Json\JsonResource;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
class ArtworkResource extends JsonResource
|
|
{
|
|
/**
|
|
* Transform the resource into an array.
|
|
*/
|
|
public function toArray($request): array
|
|
{
|
|
$md = ThumbnailPresenter::present($this->resource, 'md');
|
|
$lg = ThumbnailPresenter::present($this->resource, 'lg');
|
|
$xl = ThumbnailPresenter::present($this->resource, 'xl');
|
|
$sq = ThumbnailPresenter::present($this->resource, 'sq');
|
|
|
|
$canonicalSlug = \Illuminate\Support\Str::slug((string) ($this->slug ?: $this->title));
|
|
if ($canonicalSlug === '') {
|
|
$canonicalSlug = (string) $this->id;
|
|
}
|
|
|
|
$followerCount = 0;
|
|
if (!empty($this->user?->id)) {
|
|
if (Schema::hasTable('user_statistics')) {
|
|
$followerCount = (int) DB::table('user_statistics')
|
|
->where('user_id', (int) $this->user->id)
|
|
->value('followers_count');
|
|
}
|
|
|
|
// Legacy fallback for environments where new tables are unavailable.
|
|
if (($followerCount <= 0) && Schema::hasTable('friends_list')) {
|
|
$followerCount = (int) DB::table('friends_list')
|
|
->where('friend_id', (int) $this->user->id)
|
|
->count();
|
|
}
|
|
}
|
|
|
|
$viewerId = (int) optional($request->user())->id;
|
|
$isLiked = false;
|
|
$isFavorited = false;
|
|
$isBookmarked = false;
|
|
$isFollowing = false;
|
|
$viewerAward = null;
|
|
|
|
$bookmarksCount = Schema::hasTable('artwork_bookmarks')
|
|
? (int) DB::table('artwork_bookmarks')->where('artwork_id', (int) $this->id)->count()
|
|
: 0;
|
|
|
|
if ($viewerId > 0) {
|
|
if (Schema::hasTable('artwork_likes')) {
|
|
$isLiked = DB::table('artwork_likes')
|
|
->where('user_id', $viewerId)
|
|
->where('artwork_id', (int) $this->id)
|
|
->exists();
|
|
}
|
|
|
|
if (Schema::hasTable('artwork_bookmarks')) {
|
|
$isBookmarked = DB::table('artwork_bookmarks')
|
|
->where('user_id', $viewerId)
|
|
->where('artwork_id', (int) $this->id)
|
|
->exists();
|
|
}
|
|
|
|
$isFavorited = DB::table('artwork_favourites')
|
|
->where('user_id', $viewerId)
|
|
->where('artwork_id', (int) $this->id)
|
|
->exists();
|
|
|
|
if (!empty($this->user?->id)) {
|
|
if (Schema::hasTable('user_followers')) {
|
|
$isFollowing = DB::table('user_followers')
|
|
->where('user_id', (int) $this->user->id)
|
|
->where('follower_id', $viewerId)
|
|
->exists();
|
|
} elseif (Schema::hasTable('friends_list')) {
|
|
// Legacy fallback only.
|
|
$isFollowing = DB::table('friends_list')
|
|
->where('user_id', $viewerId)
|
|
->where('friend_id', (int) $this->user->id)
|
|
->exists();
|
|
}
|
|
}
|
|
|
|
if (Schema::hasTable('artwork_awards')) {
|
|
$viewerAward = DB::table('artwork_awards')
|
|
->where('user_id', $viewerId)
|
|
->where('artwork_id', (int) $this->id)
|
|
->value('medal');
|
|
}
|
|
}
|
|
|
|
$decode = static fn (?string $v): string => html_entity_decode((string) ($v ?? ''), ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
|
|
|
return [
|
|
'id' => (int) $this->id,
|
|
'slug' => (string) $this->slug,
|
|
'title' => $decode($this->title),
|
|
'description' => $decode($this->description),
|
|
'description_html' => $this->renderDescriptionHtml(),
|
|
'dimensions' => [
|
|
'width' => (int) ($this->width ?? 0),
|
|
'height' => (int) ($this->height ?? 0),
|
|
],
|
|
'published_at' => optional($this->published_at)->toIsoString(),
|
|
'canonical_url' => route('art.show', ['id' => (int) $this->id, 'slug' => $canonicalSlug]),
|
|
'thumbs' => [
|
|
'md' => $md,
|
|
'lg' => $lg,
|
|
'xl' => $xl,
|
|
'sq' => $sq,
|
|
],
|
|
'file' => [
|
|
'url' => $lg['url'] ?? null,
|
|
'srcset' => ThumbnailPresenter::srcsetForArtwork($this->resource),
|
|
'mime_type' => 'image/webp',
|
|
],
|
|
'user' => [
|
|
'id' => (int) ($this->user?->id ?? 0),
|
|
'name' => html_entity_decode((string) ($this->user?->name ?? ''), ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
|
'username' => (string) ($this->user?->username ?? ''),
|
|
'profile_url' => $this->user?->username ? '/@' . $this->user->username : null,
|
|
'avatar_url' => $this->user?->profile?->avatar_url,
|
|
'level' => (int) ($this->user?->level ?? 1),
|
|
'rank' => (string) ($this->user?->rank ?? 'Newbie'),
|
|
'followers_count' => $followerCount,
|
|
],
|
|
'viewer' => [
|
|
'is_bookmarked' => $isBookmarked,
|
|
'is_liked' => $isLiked,
|
|
'is_favorited' => $isFavorited,
|
|
'is_following_author' => $isFollowing,
|
|
'is_authenticated' => $viewerId > 0,
|
|
'id' => $viewerId > 0 ? $viewerId : null,
|
|
],
|
|
'stats' => [
|
|
'bookmarks' => $bookmarksCount,
|
|
'views' => (int) ($this->stats?->views ?? 0),
|
|
'downloads' => (int) ($this->stats?->downloads ?? 0),
|
|
'favorites' => (int) ($this->stats?->favorites ?? 0),
|
|
'likes' => (int) ($this->stats?->rating_count ?? 0),
|
|
],
|
|
'awards' => [
|
|
'gold' => (int) ($this->awardStat?->gold_count ?? 0),
|
|
'silver' => (int) ($this->awardStat?->silver_count ?? 0),
|
|
'bronze' => (int) ($this->awardStat?->bronze_count ?? 0),
|
|
'score' => (int) ($this->awardStat?->score_total ?? 0),
|
|
'viewer_award' => $viewerAward,
|
|
],
|
|
'categories' => $this->categories->map(fn ($category) => [
|
|
'id' => (int) $category->id,
|
|
'slug' => (string) $category->slug,
|
|
'name' => html_entity_decode((string) $category->name, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
|
'content_type_slug' => (string) ($category->contentType?->slug ?? ''),
|
|
'url' => $category->contentType ? $category->url : null,
|
|
'parent' => $category->parent ? [
|
|
'id' => (int) $category->parent->id,
|
|
'slug' => (string) $category->parent->slug,
|
|
'name' => html_entity_decode((string) $category->parent->name, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
|
'content_type_slug' => (string) ($category->parent->contentType?->slug ?? ''),
|
|
'url' => $category->parent->contentType ? $category->parent->url : null,
|
|
] : null,
|
|
])->values(),
|
|
'tags' => $this->tags->map(fn ($tag) => [
|
|
'id' => (int) $tag->id,
|
|
'slug' => (string) $tag->slug,
|
|
'name' => html_entity_decode((string) $tag->name, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
|
])->values(),
|
|
];
|
|
}
|
|
|
|
private function renderDescriptionHtml(): string
|
|
{
|
|
$rawDescription = (string) ($this->description ?? '');
|
|
|
|
if (trim($rawDescription) === '') {
|
|
return '';
|
|
}
|
|
|
|
if (! $this->authorCanPublishLinks()) {
|
|
return nl2br(e(ContentSanitizer::stripToPlain($rawDescription)));
|
|
}
|
|
|
|
return ContentSanitizer::render($rawDescription);
|
|
}
|
|
|
|
private function authorCanPublishLinks(): bool
|
|
{
|
|
$level = (int) ($this->user?->level ?? 1);
|
|
$rank = strtolower((string) ($this->user?->rank ?? 'Newbie'));
|
|
|
|
return $level > 1 && $rank !== 'newbie';
|
|
}
|
|
}
|