Vier komponierbare Scopes auf PressRelease:
- published() Status freigegeben + published_at gesetzt (ohne Zeitschranke,
damit Statistik-Fenster frei einschraenken koennen)
- visibleInArchive() published() + published_at <= jetzt (oeffentlich sichtbar)
- forPortalValues() whereIn portal
- forLanguage() where language
~19 duplizierte Query-Bloecke in routes/web.php (Home, Kategorie, Detail,
Veroeffentlichen, Suche, Newsrooms, Newsroom-Detail, Legacy-Redirect) nutzen
jetzt diese Scopes. Jedes withoutGlobalScope(PortalScope) bleibt an seiner
Stelle erhalten; die Klausel-Reihenfolge ist fuers Ergebnis irrelevant (reine
AND-Verknuepfung), daher verhaltensgleich.
Test: Web/PublishedReleaseScopeTest; die 89 bestehenden Web/-Tests bleiben gruen.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- PressRelease::scopeOwnedByApiUser() (bewusst eng: nur user_id-Autorschaft,
anders als das breitere scopeAccessibleBy) ersetzt die byte-gleiche
findOwnedPressRelease-Query in PressReleaseController + ImageController.
- apiResourceRelations()-Helfer ersetzt den 5x identischen Eager-Load-Set
(company/category.translations/images) in Index/Show/Create/Update/Reclassify.
Bewusst NICHT umgesetzt: Slug-Reimplementierung (uniqueSlug) durch
HasUniqueSlug ersetzen - der API-Fallback Str::random(8) weicht vom
Trait-slugFallback() ab (Verhaltensaenderung bei leer-slugifizierten Titeln).
Tests: neuer Scope-Test; volle Suite gruen (802 passed, 1 skipped).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- User::currentPlan() und hasUnlimitedPressReleaseQuota() pro Request
memoisiert. Beide werden je Render mehrfach abgefragt (Status-Widget auf
jeder Seite, Buchungsseite, Quota-Methoden) und loesten bisher jeweils
eigene subscription-/Plan-/payment-option-Queries aus. fresh() setzt den
Cache zurueck.
- show.blade.php: getMyPR() war NICHT memoisiert und wurde pro Request bis
zu 7x mit voller Eager-Load-Query aufgerufen -> jetzt memoisiert. Firmen-
Kennzahlen direkt per withCount() eager geladen statt nachtraeglichem
loadCount().
- Dupliziertes Zugriffsmuster (withoutGlobalScopes + user_id/company_id) aus
edit/show/index in PressRelease::scopeAccessibleBy(User) zentralisiert
(Single Source of Truth fuer Kunden-PM-Zugriff), mit Tests abgesichert.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Beim Speichern/Veroeffentlichen waren Termine 2 Stunden versetzt: die
App-Zeitzone stand auf UTC, Termine wurden nach UTC umgerechnet, aber
published_at roh angezeigt.
- config/app.php: timezone UTC -> Europe/Berlin
- PressRelease: DISPLAY_TIMEZONE + setTimezone-Umrechnung entfernt
- Admin-/Customer-Formulare: scheduledAtUtc() -> resolveScheduledAt(),
parst direkt in App-Zeitzone; Edit-Hydration ohne setTimezone
- ProofPdfRenderer + Boost-Anzeige: setTimezone entfernt
- Tests an verschiebungsfreies Verhalten angepasst
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>