belongsTo(User::class); } public function tags(): BelongsToMany { return $this->belongsToMany(Tag::class); } public function comments(): HasMany { return $this->hasMany(Comment::class); } protected function toBase64(string $path): string { $ext = $this->extension; $file = Storage::get($path); $data = base64_encode($file); return "data:image/$ext;base64,$data"; } public function getThumbUrl(): ?string { if (Storage::has("posts/$this->id/thumb")) { return $this->toBase64("posts/$this->id/thumb"); } return $this->getPreviewUrl(); } public function getPreviewUrl(): ?string { if (Storage::has("posts/$this->id/preview")) { return $this->toBase64("posts/$this->id/preview"); } return $this->getFullUrl(); } public function getFullUrl(): ?string { if (Storage::has("posts/$this->id/full")) { return $this->toBase64("posts/$this->id/full"); } abort(404); } public function getMimeType(): ?string { return Storage::mimeType("posts/$this->id/full"); } public function getDimensions(): false|array { return getimagesize($this->getFullUrl()); } public function getDimensionsStr(): string { [$width, $height] = $this->getDimensions(); return "$width x $height"; } public function getFileSize(): int { return Storage::size("posts/$this->id/full"); } public function getAspectRatio(): string { list($width, $height) = $this->getDimensions(); $divisor = gmp_intval(gmp_gcd($width, $height)); $w = $width / $divisor; $h = $height / $divisor; return "aspect-ratio: $w/$h;"; } public function download(): StreamedResponse { return Storage::download("posts/$this->id/full"); } public function getNextPost(): ?Post { return Post::where('created_at', '>', $this->created_at) ->orderBy('created_at', 'asc') ->first(); } public function getPreviousPost(): ?Post { return Post::where('created_at', '<', $this->created_at) ->orderBy('created_at', 'desc') ->first(); } public function getRatingColor(): string { return match ($this->rating) { 'safe' => 'success', 'suggestive' => 'warning', 'explicit' => 'danger', default => 'default', }; } }