Startseite und Heroes - Hero-Slideshow (11 Motive inkl. Febrü) mit Infokarte, Laufzeit-Linie, größeren Klickflächen, Goldrahmen und mobiler Karte unter dem Bild; Zeile über der Überschrift, neue Vertrauenspunkte - Hero-Stil auf Marken, Über uns und Kontakt übertragen, Breadcrumb entfernt - Gründer-Leiste, Vision-Box auf Ocker, Showroom-Display in Box mit „Größer ansehen“/Vollbild - Akzentfarbe #a8741f, größere Serif-Überschriften in der Interior-Welt - Marken: Bildpause mit Zitat; Vereine aktualisiert und verlinkt Inhalte - Lektorat aller angezeigten Texte, /about-Korrekturen, Rechtstexte (DDG, TDDDG, Hosting Hetzner) - Ablauf Maßanfertigung überall einheitlich, Magazin-Beitrag neu, alte Beiträge offline, deutsches Datum/Lesezeit, FAQ Projektausstattung, Otterpohl - Referenzen-Seite per CMS-Schalter ausblendbar CMS und Technik - Tote Sektionen, Felder, Seiten und Komponenten entfernt und archiviert (dev/2026-08-28/archiv-*) - Entwurf /entwurf, Farb-Schalter und /welcome entfernt; Test-Routen nur noch lokal - Seitenbaum-Beschreibungen geprüft, fehlende CMS-Felder ergänzt, Markenliste aus „Kernmarken“ - Admin-Bildvorschauen repariert, verwendete Bilder in die Mediathek übernommen - Seeder für das Deployment siehe dev/2026-08-28/entwicklungsplan.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
125 lines
3.8 KiB
PHP
125 lines
3.8 KiB
PHP
<?php
|
||
|
||
namespace Database\Seeders\Concerns;
|
||
|
||
use App\Models\CmsArticle;
|
||
use App\Models\CmsBrand;
|
||
use FluxCms\Core\Models\CmsContent;
|
||
use FluxCms\Core\Services\CmsContentService;
|
||
use Illuminate\Database\Eloquent\Model;
|
||
|
||
/**
|
||
* Textersetzungen über alle gepflegten Inhalte: CMS-Sektionen (alle Sprachen), Marken und
|
||
* Magazinbeiträge. Ersetzt wird per strtr() – idempotent, solange der neue Text den alten nicht
|
||
* enthält. `$exact` ersetzt nur Werte, die vollständig übereinstimmen.
|
||
*/
|
||
trait ReplacesCmsTexts
|
||
{
|
||
/** @var list<string> */
|
||
private array $brandFields = [
|
||
'name', 'tagline', 'teaser', 'summary', 'description', 'widget_label', 'cta_title', 'cta_text',
|
||
'origin_city', 'origin_distance', 'origin_role', 'highlights', 'services', 'sections', 'gallery',
|
||
];
|
||
|
||
/** @var list<string> */
|
||
private array $articleFields = ['title', 'subtitle', 'content'];
|
||
|
||
/**
|
||
* @param array<string, string> $replacements
|
||
* @param array<string, string> $exact
|
||
* @return int Anzahl geänderter Textstellen
|
||
*/
|
||
protected function replaceCmsTexts(array $replacements, array $exact = []): int
|
||
{
|
||
$count = 0;
|
||
$groups = [];
|
||
|
||
foreach (CmsContent::query()->get() as $row) {
|
||
$changes = 0;
|
||
$row->value = $this->replaceDeep($row->getTranslations('value'), $replacements, $exact, $changes);
|
||
|
||
if ($changes > 0) {
|
||
$row->save();
|
||
$groups[$row->group] = true;
|
||
$count += $changes;
|
||
}
|
||
}
|
||
|
||
foreach (array_keys($groups) as $group) {
|
||
app(CmsContentService::class)->clearCache($group);
|
||
}
|
||
|
||
foreach (CmsBrand::query()->get() as $brand) {
|
||
$count += $this->replaceInModel($brand, $this->brandFields, $replacements, $exact);
|
||
}
|
||
|
||
foreach (CmsArticle::query()->get() as $article) {
|
||
$count += $this->replaceInModel($article, $this->articleFields, $replacements, $exact);
|
||
}
|
||
|
||
return $count;
|
||
}
|
||
|
||
/**
|
||
* @param list<string> $fields
|
||
* @param array<string, string> $replacements
|
||
* @param array<string, string> $exact
|
||
*/
|
||
private function replaceInModel(Model $model, array $fields, array $replacements, array $exact): int
|
||
{
|
||
$changes = 0;
|
||
$translatable = property_exists($model, 'translatable') ? $model->translatable : [];
|
||
|
||
foreach ($fields as $field) {
|
||
$isTranslatable = in_array($field, $translatable, true);
|
||
$value = $isTranslatable ? $model->getTranslations($field) : $model->getAttribute($field);
|
||
|
||
if (! is_array($value)) {
|
||
continue;
|
||
}
|
||
|
||
$before = $changes;
|
||
$value = $this->replaceDeep($value, $replacements, $exact, $changes);
|
||
|
||
if ($changes > $before) {
|
||
$isTranslatable ? $model->setTranslations($field, $value) : $model->setAttribute($field, $value);
|
||
}
|
||
}
|
||
|
||
if ($changes > 0) {
|
||
$model->save();
|
||
}
|
||
|
||
return $changes;
|
||
}
|
||
|
||
/**
|
||
* @param array<mixed> $data
|
||
* @param array<string, string> $replacements
|
||
* @param array<string, string> $exact
|
||
* @return array<mixed>
|
||
*/
|
||
private function replaceDeep(array $data, array $replacements, array $exact, int &$count): array
|
||
{
|
||
foreach ($data as $key => $item) {
|
||
if (is_array($item)) {
|
||
$data[$key] = $this->replaceDeep($item, $replacements, $exact, $count);
|
||
|
||
continue;
|
||
}
|
||
|
||
if (! is_string($item)) {
|
||
continue;
|
||
}
|
||
|
||
$replaced = $exact[$item] ?? strtr($item, $replacements);
|
||
|
||
if ($replaced !== $item) {
|
||
$data[$key] = $replaced;
|
||
$count++;
|
||
}
|
||
}
|
||
|
||
return $data;
|
||
}
|
||
}
|