- /de/category/{slug}/archiv/{jahr} (CategoryArchivePageData,
CategoryArchiveController, View kategorie-archiv): 30 Meldungen je
Seite, neueste zuerst, Jahresleiste mit Zahlen; ohne Jahr das juengste
Jahr mit Meldungen. Canonical mit ?page=N auf Folgeseiten, hreflang
nur auf Seite 1, CollectionPage + BreadcrumbList. Gecacht bis Seite 3.
Leere Jahre, unbekannte Kategorien, leere Folgeseiten: 404.
- Branchenseite: Jahresleiste unter dem Feed (archiveYears, eine
gruppierte Query); Sitemap listet alle Jahresarchive.
- categories:seed-descriptions {--dry-run} {--force}: fuellt leere DE/EN
Beschreibungen aus database/seeders/data/category-descriptions.php
(14 Kategorien, sachlich, ohne Werbeaussagen), leert den Seiten-Cache.
- Branchenseite: Titel trug config('app.name') ("– pressekonto") statt
des Portalnamens — jetzt presseecho/businessportal24.
- Protokoll Teil 5 (2.3 mit Befund: 0 von 14 Beschreibungen, Sonstiges =
28 % des Bestands), Roadmap 2.3 abgehakt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
83 lines
2.8 KiB
PHP
83 lines
2.8 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Category;
|
|
use App\Models\CategoryTranslation;
|
|
use App\Support\WebPageCache;
|
|
use Illuminate\Console\Command;
|
|
|
|
/**
|
|
* Beschreibungen der Branchenseiten einspielen (Roadmap 2.3). Ohne eigene
|
|
* Beschreibung zeigen alle Branchenseiten denselben Standardsatz — für
|
|
* Suchmaschinen 14 gleich aussehende Seiten. Texte liegen in
|
|
* database/seeders/data/category-descriptions.php, Schlüssel ist der
|
|
* DE-Slug. Nur leere Felder werden gefüllt; --force überschreibt.
|
|
*/
|
|
class SeedCategoryDescriptions extends Command
|
|
{
|
|
protected $signature = 'categories:seed-descriptions
|
|
{--dry-run : Nur zeigen, was geschrieben würde}
|
|
{--force : Auch vorhandene Beschreibungen überschreiben}';
|
|
|
|
protected $description = 'Füllt leere Kategoriebeschreibungen (DE/EN) aus database/seeders/data/category-descriptions.php.';
|
|
|
|
public function handle(): int
|
|
{
|
|
/** @var array<string, array<string, string>> $texts */
|
|
$texts = require database_path('seeders/data/category-descriptions.php');
|
|
|
|
$rows = [];
|
|
$written = 0;
|
|
|
|
foreach ($texts as $slug => $byLocale) {
|
|
$category = Category::query()
|
|
->whereHas('translations', fn ($query) => $query->where('locale', 'de')->where('slug', $slug))
|
|
->with('translations')
|
|
->first();
|
|
|
|
if (! $category) {
|
|
$rows[] = [$slug, '—', 'Kategorie nicht gefunden'];
|
|
|
|
continue;
|
|
}
|
|
|
|
foreach ($byLocale as $locale => $text) {
|
|
/** @var CategoryTranslation|null $translation */
|
|
$translation = $category->translations->firstWhere('locale', $locale);
|
|
|
|
if (! $translation) {
|
|
$rows[] = [$slug, $locale, 'keine Übersetzung'];
|
|
|
|
continue;
|
|
}
|
|
|
|
if (filled($translation->description) && ! $this->option('force')) {
|
|
$rows[] = [$slug, $locale, 'bereits vorhanden, übersprungen'];
|
|
|
|
continue;
|
|
}
|
|
|
|
$rows[] = [$slug, $locale, mb_strimwidth($text, 0, 60, '…')];
|
|
|
|
if (! $this->option('dry-run')) {
|
|
$translation->forceFill(['description' => $text])->save();
|
|
$written++;
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->table(['Kategorie', 'Sprache', 'Ergebnis'], $rows);
|
|
|
|
if ($this->option('dry-run')) {
|
|
$this->info('[Dry-Run] Nichts geschrieben.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
WebPageCache::flush();
|
|
$this->info(sprintf('%d Beschreibungen geschrieben, Seiten-Cache geleert.', $written));
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
}
|