160 lines
9.2 KiB
PHP
160 lines
9.2 KiB
PHP
<?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,
|
||
));
|
||
}
|
||
}
|
||
}
|