*/ public const GALLERY_CATEGORIES = [self::GALLERY_PROJECT, self::GALLERY_INSPIRATION]; protected $table = 'cms_brands'; protected $fillable = [ 'slug', 'name', 'tagline', 'teaser', 'summary', 'highlights', 'description', 'logo', 'image', 'services', 'gallery', 'website_url', 'showroom', 'is_published', 'order', ]; /** @var array */ public array $translatable = [ 'name', 'tagline', 'teaser', 'summary', 'description', ]; protected function casts(): array { return [ 'highlights' => 'array', 'services' => 'array', 'gallery' => 'array', 'is_published' => 'boolean', 'order' => 'integer', ]; } public function scopePublished(Builder $query): Builder { return $query->where('is_published', true); } public function scopeOrdered(Builder $query): Builder { return $query->orderBy('order')->orderBy('id'); } /** * Veröffentlichte Kernmarken fürs Frontend, nach Slug indiziert. * * Das CMS gewinnt. Solange keine Marke gepflegt ist, greift die Lang-Sektion `core_brands` * als Fallback – dieselbe Reihenfolge wie bei cms_theme_section(), damit die Startseite auf * einer frischen Installation nicht ohne Kernmarken dasteht. * * @return array> */ public static function forFrontend(): array { $brands = static::query()->published()->ordered()->get(); if ($brands->isNotEmpty()) { return $brands ->mapWithKeys(fn (self $brand) => [$brand->slug => $brand->toFrontendArray()]) ->all(); } return static::fallbackFromLang(); } /** * @return array> */ private static function fallbackFromLang(): array { $section = cms_theme_section('core_brands'); $brands = is_array($section) ? ($section['brands'] ?? []) : []; $out = []; foreach ($brands as $brand) { if (! is_array($brand) || empty($brand['name'])) { continue; } $slug = $brand['slug'] ?? \Illuminate\Support\Str::slug((string) $brand['name']); $entry = array_merge([ 'slug' => $slug, 'tagline' => '', 'teaser' => '', 'summary' => '', 'highlights' => [], 'description' => '', 'logo' => '', 'image' => '', 'services' => [], 'gallery' => [], 'website_url' => '', 'showroom' => '', 'has_detail_page' => false, ], $brand, ['slug' => $slug, 'has_detail_page' => false]); $entry['gallery'] = self::normalizeGallery($entry['gallery']); $out[$slug] = $entry; } return $out; } /** * Galerie-Eintraege in eine feste Form bringen. * * Ein Eintrag ohne (oder mit unbekannter) Kategorie gilt als Inspiration, nicht als Projekt: * Ein Entwurf, der versehentlich als Referenz durchgeht, waere die schaedlichere Verwechslung. * * @param mixed $gallery * @return list */ public static function normalizeGallery($gallery): array { if (! is_array($gallery)) { return []; } $out = []; foreach ($gallery as $item) { $image = is_array($item) ? (string) ($item['image'] ?? '') : (string) $item; $image = trim($image); if ($image === '') { continue; } $category = is_array($item) ? (string) ($item['category'] ?? '') : ''; $out[] = [ 'image' => $image, 'category' => in_array($category, self::GALLERY_CATEGORIES, true) ? $category : self::GALLERY_INSPIRATION, 'caption' => is_array($item) ? trim((string) ($item['caption'] ?? '')) : '', ]; } return $out; } /** * Galerie nach realisierten Projekten und Inspirationen getrennt. * * @param mixed $gallery * @return array{projects: list, inspirations: list} */ public static function groupGallery($gallery): array { $items = self::normalizeGallery($gallery); return [ 'projects' => array_values(array_filter( $items, fn (array $item) => $item['category'] === self::GALLERY_PROJECT, )), 'inspirations' => array_values(array_filter( $items, fn (array $item) => $item['category'] === self::GALLERY_INSPIRATION, )), ]; } /** * @return array */ public function toFrontendArray(): array { return [ 'id' => $this->id, 'slug' => $this->slug, 'name' => $this->name, 'tagline' => $this->tagline, 'teaser' => $this->teaser, 'summary' => $this->summary, 'highlights' => $this->highlights ?? [], 'description' => $this->description, 'logo' => $this->logo, 'image' => $this->image, 'services' => $this->services ?? [], 'gallery' => self::normalizeGallery($this->gallery), 'website_url' => $this->website_url, 'showroom' => $this->showroom, 'has_detail_page' => true, ]; } }