R4.3: Karten-Metadaten-Logik als PressRelease-Praesentations-Helper
localizedCategoryName/cardImageUrl/teaserText/wordCount/readTimeMinutes/ compactPublishedLabel ersetzen die 5x kopierte @php-Logik der Kartenkomponenten; Lesezeit-Formel vereinheitlicht (ceil -> round in HomePageData-Spotlight). Tests: Web/PressReleaseCardHelpersTest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
459b339a9b
commit
01e175e138
4 changed files with 137 additions and 3 deletions
|
|
@ -26,6 +26,7 @@ use Illuminate\Pagination\Paginator;
|
|||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\HtmlString;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class PressRelease extends Model
|
||||
{
|
||||
|
|
@ -148,6 +149,77 @@ class PressRelease extends Model
|
|||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kategorie-Name in der Anzeigesprache, Fallback auf die erste
|
||||
* vorhandene Übersetzung. Zentrale Ablöse der zuvor in jeder
|
||||
* Kartenkomponente kopierten Auflösung (R4.3).
|
||||
*/
|
||||
public function localizedCategoryName(?string $locale = null): ?string
|
||||
{
|
||||
$locale ??= app()->getLocale();
|
||||
|
||||
$translation = $this->category?->translations?->firstWhere('locale', $locale)
|
||||
?? $this->category?->translations?->first();
|
||||
|
||||
return $translation?->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bild-URL für Kartenansichten: card-Variante des ersten Bildes,
|
||||
* Fallback Original. Null bei bildlosen PMs (dann greift
|
||||
* chosenPlaceholderUrl() bzw. der generische Fallback der Komponente).
|
||||
*/
|
||||
public function cardImageUrl(): ?string
|
||||
{
|
||||
$image = $this->images?->first();
|
||||
|
||||
return $image?->variantUrl('card') ?? $image?->url();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag-freier, whitespace-normalisierter Anriss des PM-Textes.
|
||||
*/
|
||||
public function teaserText(int $limit = 180): string
|
||||
{
|
||||
return (string) Str::of(strip_tags((string) $this->text))->squish()->limit($limit);
|
||||
}
|
||||
|
||||
public function wordCount(): int
|
||||
{
|
||||
return str_word_count(strip_tags((string) $this->text));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lesezeit in Minuten (200 Wörter/Minute, mindestens 1).
|
||||
*/
|
||||
public function readTimeMinutes(): int
|
||||
{
|
||||
return max(1, (int) round($this->wordCount() / 200));
|
||||
}
|
||||
|
||||
/**
|
||||
* Kompakter Zeitstempel der Kartenkomponenten: heute „HH:MM",
|
||||
* gestern lokalisiert, sonst Kurzdatum. Null ohne published_at.
|
||||
*/
|
||||
public function compactPublishedLabel(): ?string
|
||||
{
|
||||
$publishedAt = $this->published_at;
|
||||
|
||||
if (! $publishedAt) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($publishedAt->isToday()) {
|
||||
return $publishedAt->format('H:i');
|
||||
}
|
||||
|
||||
if ($publishedAt->isYesterday()) {
|
||||
return __('web.shared.yesterday');
|
||||
}
|
||||
|
||||
return $publishedAt->isoFormat('D. MMM');
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue