b2in/database/seeders/BrandImageSeeder.php

160 lines
9.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Database\Seeders;
use App\Models\CmsBrand;
use Illuminate\Database\Seeder;
/**
* Trägt Titelbild und Galerie für CABINET, Rotpunkt, Febrü (Nachtrag 16) und Otterpohl (Nachtrag 19) nach.
*
* Grundlage: dev/2026-08-28/images/ (Zulieferungen vom 22.–24.09.2026). Die Originale sind 1–8 MB
* große JPEGs; unter public/img/assets/marken/{cabinet,rotpunkt,februe,otterpohl}/ liegen sie als
* WebP mit maximal 1920 px Kantenlänge (Imagick, Qualität 82, ohne Metadaten). Die mit `_title_`
* markierte Datei ist das Titelbild (Seitenkopf der Markenseite, Kachel auf der Startseite,
* Markenblock auf /marken). Die Galeriebilder der drei Hersteller stehen als **Visualisierung**:
* es sind Herstellerdarstellungen, keine von uns ausgeführten Projekte – unter „Referenzen“
* erscheinen sie damit nicht. Bei Otterpohl sind die Bilder 2–5 Einblicke in Werkstatt und
* Montage (**Aus der Werkstatt**), alle übrigen ausgeführte Aufträge (**Realisiertes Projekt**);
* letztere erscheinen unter „Referenzen“, solange dort keine eigenen Einträge gepflegt sind.
*
* Verhalten: Das Titelbild wird nur gesetzt, wenn keins gepflegt ist. Galeriebilder werden
* nur ergänzt, wenn die Datei noch nicht in der Galerie steht; vorhandene Einträge bleiben
* samt Kategorie und Bildunterschrift, wie Marcel sie gepflegt hat. Mehrfaches Ausführen ist
* unbedenklich.
*
* php artisan db:seed --class=BrandImageSeeder
*/
class BrandImageSeeder extends Seeder
{
/**
* Galerie: Dateiname → Bildunterschrift (Kategorie Visualisierung) oder
* Dateiname → ['caption' => …, 'category' => …] für eine andere Kategorie.
*
* @var array<string, array{image: string, gallery: array<string, string|array{caption: string, category: string}>}>
*/
private const IMAGES = [
'cabinet' => [
'image' => 'marken/cabinet/ankleide-solitaer-eiche-tano.webp',
'gallery' => [
'marken/cabinet/dachschraegenschrank-filo-cashmere.webp' => 'Dachschrägenschrank in Filo Cashmere',
'marken/cabinet/schrank-gegen-schraege-marmor.webp' => 'Schrank gegen die Schräge in Marmoroptik',
'marken/cabinet/schlafzimmer-eiche-tano.webp' => 'Schlafzimmerschrank in Eiche Tano',
'marken/cabinet/schlafzimmer-velluto-fango.webp' => 'Schlafzimmerschrank in Velluto Fango',
'marken/cabinet/schlafzimmer-wandschrank-filo-cashmere.webp' => 'Wandschrank im Schlafzimmer in Filo Cashmere',
'marken/cabinet/garderobe-seite-offen.webp' => 'Garderobe mit offener Seite',
'marken/cabinet/garderobe-sitznische-filo-cashmere.webp' => 'Garderobe mit Sitznische in Filo Cashmere',
'marken/cabinet/drehtuerenschrank-marmor.webp' => 'Drehtürenschrank in Marmoroptik',
'marken/cabinet/flur-schrank-eiche-tano.webp' => 'Flurschrank in Eiche Tano',
'marken/cabinet/dachschraege-velluto-fango.webp' => 'Schrank unter der Dachschräge in Velluto Fango',
'marken/cabinet/ankleide-solitaer-eiche-tano-seite.webp' => 'Ankleide Solitär in Eiche Tano, Seitenansicht',
],
],
'rotpunkt' => [
'image' => 'marken/rotpunkt/kueche-01.webp',
'gallery' => [
'marken/rotpunkt/kueche-01-b.webp' => 'Küche 01, zweite Ansicht',
'marken/rotpunkt/kueche-02.webp' => 'Küche 02',
'marken/rotpunkt/kueche-03.webp' => 'Küche 03',
'marken/rotpunkt/kueche-04.webp' => 'Küche 04',
'marken/rotpunkt/kueche-05.webp' => 'Küche 05',
'marken/rotpunkt/kueche-06.webp' => 'Küche 06',
'marken/rotpunkt/kueche-06-b.webp' => 'Küche 06, zweite Ansicht',
'marken/rotpunkt/kueche-07.webp' => 'Küche 07',
'marken/rotpunkt/kueche-08.webp' => 'Küche 08',
'marken/rotpunkt/kueche-09.webp' => 'Küche 09',
'marken/rotpunkt/kueche-10.webp' => 'Küche 10',
'marken/rotpunkt/kueche-11.webp' => 'Küche 11',
'marken/rotpunkt/kueche-12.webp' => 'Küche 12',
],
],
// Bildunterschriften nach den Febrü-Produktlinien aus den Dateinamen.
'februe' => [
'image' => 'marken/februe/base-thekenloesung.webp',
'gallery' => [
'marken/februe/active-2-0-bureo.webp' => 'Active 2.0 mit Bureo',
'marken/februe/active-2-0-soul-grossraum.webp' => 'Großraum mit Active 2.0 und Soul',
'marken/februe/adesso.webp' => 'Adesso',
'marken/februe/arena-stage.webp' => 'Arena Stage',
'marken/februe/base.webp' => 'Base',
'marken/februe/base-sideboard.webp' => 'Base Sideboard',
'marken/februe/bobb-bionics-coworker-container-cube.webp' => 'Bobb, Bionics, CoWorker, Container und Cube',
'marken/februe/bobb.webp' => 'Bobb',
'marken/februe/brandon.webp' => 'Brandon',
'marken/februe/coworker.webp' => 'CoWorker',
'marken/februe/corporate.webp' => 'Corporate',
'marken/februe/curved-ben-basic.webp' => 'Curved, Ben und Basic',
'marken/februe/eline-one-silent-garderobenpaneel.webp' => 'E-Line, One, Silent und Garderobenpaneel',
'marken/februe/elements-soul-grossraum.webp' => 'Großraum mit Elements und Soul',
'marken/februe/vio.webp' => 'Vio',
],
],
// Otterpohl (Zulieferung 24.09.): Titelbild und 2–5 aus der Werkstatt, der Rest sind Referenzen.
// Unterschriften ohne Kundennamen – die stehen nur in den Dateinamen der Zulieferung.
'tischlerei' => [
'image' => 'marken/otterpohl/werkstatt-titel.webp',
'gallery' => [
'marken/otterpohl/referenz-luecke-01.webp' => ['caption' => 'Treppe mit Lamellenwand, Sitzbank und Sideboard', 'category' => CmsBrand::GALLERY_PROJECT],
'marken/otterpohl/referenz-dziuballe-treppe.webp' => ['caption' => 'Treppe mit Holzstufen, Stufenbeleuchtung und Eichenhandlauf', 'category' => CmsBrand::GALLERY_PROJECT],
'marken/otterpohl/referenz-luecke-12.webp' => ['caption' => 'Tür und Kommode vor Lamellenwand', 'category' => CmsBrand::GALLERY_PROJECT],
'marken/otterpohl/referenz-neugebauer.webp' => ['caption' => 'Gewendelte Treppe mit Eichenstufen', 'category' => CmsBrand::GALLERY_PROJECT],
'marken/otterpohl/referenz-luecke-15.webp' => ['caption' => 'Beleuchtete Wandregale über Eck', 'category' => CmsBrand::GALLERY_PROJECT],
'marken/otterpohl/referenz-berkemeier-treppe.webp' => ['caption' => 'Treppe mit umlaufender Sockelleiste und Lichtdetail', 'category' => CmsBrand::GALLERY_PROJECT],
'marken/otterpohl/referenz-objektbau-luecke-technik.webp' => ['caption' => 'Objektbau: Verkaufsraum mit Theke und Regalwand', 'category' => CmsBrand::GALLERY_PROJECT],
'marken/otterpohl/referenz-otterpohl-11.webp' => ['caption' => 'Sideboard mit Eichenplatte im Büro', 'category' => CmsBrand::GALLERY_PROJECT],
'marken/otterpohl/werkstatt-02.webp' => ['caption' => 'CNC-Bearbeitungszentrum in der Fertigung', 'category' => CmsBrand::GALLERY_COMPANY],
'marken/otterpohl/werkstatt-03.webp' => ['caption' => 'Einbau einer Tür vor Ort', 'category' => CmsBrand::GALLERY_COMPANY],
'marken/otterpohl/werkstatt-04.webp' => ['caption' => 'Handwerkzeug in der Werkstatt', 'category' => CmsBrand::GALLERY_COMPANY],
'marken/otterpohl/werkstatt-05-lift.webp' => ['caption' => 'Anlieferung per Möbellift – Montage inklusive', 'category' => CmsBrand::GALLERY_COMPANY],
],
],
];
public function run(): void
{
foreach (self::IMAGES as $slug => $data) {
$brand = CmsBrand::query()->where('slug', $slug)->first();
if (! $brand) {
$this->command?->warn("Marke „{$slug}“ nicht gefunden – übersprungen.");
continue;
}
$titleSet = false;
if (trim((string) $brand->image) === '') {
$brand->image = $data['image'];
$titleSet = true;
}
$gallery = CmsBrand::normalizeGallery($brand->gallery);
$known = array_column($gallery, 'image');
$added = 0;
foreach ($data['gallery'] as $image => $entry) {
if (in_array($image, $known, true)) {
continue;
}
$gallery[] = [
'image' => $image,
'category' => is_array($entry) ? $entry['category'] : CmsBrand::GALLERY_INSPIRATION,
'caption' => is_array($entry) ? $entry['caption'] : $entry,
];
$added++;
}
$brand->gallery = $gallery;
$brand->save();
$this->command?->info(sprintf(
'Marke „%s“: Titelbild %s, %d Galeriebilder ergänzt, %d vorhanden.',
$slug,
$titleSet ? 'gesetzt' : 'behalten',
$added,
count($gallery) - $added,
));
}
}
}