'int', 'size' => 'int', 'include_in_pdf' => 'bool', ]; /** * Icon-Klassen nach Extension (kompatibel zu BookingFile::$icon_ext). * @var array */ public static $icon_ext = [ 'default' => 'fa fa-file', 'pdf' => 'fa fa-file-pdf', 'jpg' => 'fa fa-file-image', 'jpeg' => 'fa fa-file-image', 'png' => 'fa fa-file-image', 'doc' => 'fa fa-file-word', 'docx' => 'fa fa-file-word', ]; public function offerVersion(): BelongsTo { return $this->belongsTo(OfferVersion::class, 'offer_version_id'); } public function getIconExt(): string { return self::$icon_ext[$this->ext] ?? self::$icon_ext['default']; } /** * Download/Preview-URL. Der zweite Parameter der Storage-Route (`offer`) * wird vom `storage_file`-Controller für Disk-Auswahl ausgewertet — * muss serverseitig freigeschaltet sein (siehe Ticket B4 / StorageController). * * @param bool|string $download false = inline, 'download' = Attachment */ public function getURL($download = false): string { return route('storage_file', [$this->id, 'offer', $download]); } public function getPath(): string { // gleiches Idiom wie BookingFile::getPath() — Intelephense sieht // path() im Filesystem-Contract in diesem Kontext nicht zuverlässig, // php -l ist sauber; Methode ist Teil der Laravel-Filesystem-API seit 9.x. /** @phpstan-ignore-next-line */ return \Storage::disk('offer')->path($this->dir . $this->filename); } public function formatBytes(int $precision = 2): string { $size = (int) $this->size; if ($size <= 0) { return '0 bytes'; } $base = log($size) / log(1024); $suffixes = [' bytes', ' KB', ' MB', ' GB', ' TB']; return round(pow(1024, $base - floor($base)), $precision) . $suffixes[(int) floor($base)]; } }