resource instanceof MissingValue) { return []; } $get = function ($key) { $r = $this->resource; if ($r instanceof MissingValue || $r === null) { return null; } // Eloquent model: prefer getAttribute to avoid magic proxies if (method_exists($r, 'getAttribute')) { return $r->getAttribute($key); } if (is_array($r)) { return $r[$key] ?? null; } if (is_object($r)) { return $r->{$key} ?? null; } return null; }; $hash = (string) ($get('hash') ?? ''); $fileExt = (string) ($get('file_ext') ?? ''); $filesBase = rtrim((string) config('cdn.files_url', ''), '/'); $buildOriginalUrl = static function (string $hashValue, string $extValue) use ($filesBase): ?string { $normalizedHash = strtolower((string) preg_replace('/[^a-f0-9]/', '', $hashValue)); $normalizedExt = strtolower((string) preg_replace('/[^a-z0-9]/', '', $extValue)); if ($normalizedHash === '' || $normalizedExt === '') return null; $h1 = substr($normalizedHash, 0, 2); $h2 = substr($normalizedHash, 2, 2); if ($h1 === '' || $h2 === '' || $filesBase === '') return null; return sprintf('%s/originals/%s/%s/%s.%s', $filesBase, $h1, $h2, $normalizedHash, $normalizedExt); }; return [ 'slug' => $get('slug'), 'title' => $get('title'), 'description' => $get('description'), 'width' => $get('width'), 'height' => $get('height'), // File URLs are derived from hash/ext (no DB path dependency) 'file' => [ 'name' => $get('file_name') ?? null, 'url' => $this->when(! empty($hash) && ! empty($fileExt), fn() => $buildOriginalUrl($hash, $fileExt)), 'size' => $get('file_size') ?? null, 'mime_type' => $get('mime_type') ?? null, ], 'categories' => $this->whenLoaded('categories', function () { return $this->categories->map(fn($c) => [ 'slug' => $c->slug ?? null, 'name' => $c->name ?? null, ])->values(); }), 'published_at' => $this->whenNotNull($get('published_at') ? $this->published_at->toAtomString() : null), 'urls' => [ 'canonical' => $get('canonical_url') ?? null, ], ]; } }