'array', 'file_size' => 'integer', 'offloaded_at' => 'datetime', ]; /** * Get the category. */ public function getCategory(): ?string { return $this->category; } /** * Get metadata value by key. */ public function getMetadata(?string $key = null): mixed { if ($key === null) { return $this->metadata; } return $this->metadata[$key] ?? null; } /** * Get the original filename from metadata. */ public function getOriginalName(): ?string { return $this->getMetadata('original_name'); } /** * Check if this offload is for a specific category. */ public function isCategory(string $category): bool { return $this->getCategory() === $category; } /** * Check if the file is an image. */ public function isImage(): bool { return $this->mime_type && str_starts_with($this->mime_type, 'image/'); } /** * Check if the file is a video. */ public function isVideo(): bool { return $this->mime_type && str_starts_with($this->mime_type, 'video/'); } /** * Check if the file is audio. */ public function isAudio(): bool { return $this->mime_type && str_starts_with($this->mime_type, 'audio/'); } /** * Scope to filter by category. */ public function scopeCategory($query, string $category) { return $query->where('category', $category); } /** * Alias for scopeCategory - filter by category. */ public function scopeInCategory($query, string $category) { return $this->scopeCategory($query, $category); } /** * Scope to filter by disk. */ public function scopeDisk($query, string $disk) { return $query->where('disk', $disk); } /** * Alias for scopeDisk - filter by disk. */ public function scopeForDisk($query, string $disk) { return $this->scopeDisk($query, $disk); } /** * Get human-readable file size. */ public function getFileSizeHumanAttribute(): string { $bytes = $this->file_size ?? 0; $units = ['B', 'KB', 'MB', 'GB', 'TB']; $power = $bytes > 0 ? floor(log($bytes, 1024)) : 0; $power = min($power, count($units) - 1); return round($bytes / (1024 ** $power), 2).' '.$units[$power]; } }