presseportale/app/Support/WebPortalContext.php
Kevin Adametz 5dcaf4e7b0 web: E9 und E10 entschieden — Zuordnung aktiv, eine Adresse je statischer Seite, Hub-Portalseiten leiten weiter
E9: Kategorie-Zuordnung wie vorgeschlagen übernommen, Zuordnung ist
standardmäßig an (CANONICAL_ASSIGNMENT_ENABLED). Auf der Dev-Kopie
verifiziert: Kopie trägt rel=canonical auf die Erstquelle und fällt aus der
Sitemap ihres Portals.

E10: faq, hilfe, gute-pressemitteilung, die vier Transparenzseiten und die
API-Doku lagen auf allen drei Hosts mit identischem Text und je eigenem
Self-Canonical. Jetzt führt presseecho die Informationsseiten, der Hub die
API-Doku; Sitemap und llms.txt nennen nur die führende Adresse.
Rechtstexte (Impressum, Datenschutz, AGB, Richtlinien, Meldeweg,
Kündigung) bleiben bewusst je Host — jede Domain ist ein eigenes Angebot
mit eigener Anbieterkennzeichnung.

Bei der Erreichbarkeitsprüfung des Hubs gefunden und behoben:
/de/preise, /de/veroeffentlichen, /de/newsrooms und /de/suche wurden unter
pressekonto.com mit dem Branding von businessportal24 ausgeliefert (der
Portal-Kontext fällt dort darauf zurück) — jetzt 301 auf presseecho, die
Transparenz-Navigation verlinkt direkt dorthin. /de/kontakt und
/de/ueber-uns sprangen über /de auf die Startseite, jetzt in einem Schritt.

Der Self-Canonical kommt jetzt aus dem aufgerufenen Host; Portal-Inhalte,
die über den Hub laufen, behalten ihr Portal (webPortalContextApplied).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-18 07:52:09 +00:00

57 lines
1.9 KiB
PHP

<?php
namespace App\Support;
use App\Enums\Portal;
use Illuminate\Support\Facades\View;
/**
* Öffentlicher Portal-Kontext (Presseecho/Businessportal24) einer Web-Landingpage,
* abgeleitet aus dem Host. Bündelt die zuvor in jeder Route-Closure wiederholte
* Host→Portal-Ableitung samt Anwendung der Domain-/Theme-Konfiguration.
*/
class WebPortalContext
{
/**
* @param list<string> $portalValues Eigenes Portal plus `both`.
* @param array<string, mixed> $domainConfig
*/
private function __construct(
public readonly string $domainKey,
public readonly Portal $portal,
public readonly string $language,
public readonly array $portalValues,
public readonly array $domainConfig,
) {}
/**
* Portal-Ableitung ohne Seiteneffekte (kein Anwenden der Domain-Config) —
* für Komponenten, die nur wissen müssen, auf welchem Portal sie rendern.
*/
public static function portalFromHost(): Portal
{
return str_contains(request()->getHost(), 'presseecho')
? Portal::Presseecho
: Portal::Businessportal24;
}
public static function fromRequest(): self
{
$portal = self::portalFromHost();
$domainKey = $portal === Portal::Presseecho ? 'presseecho' : 'businessportal24';
// Merker fürs Layout: Diese Seite rendert Portal-Inhalte, die
// Domain-Config zeigt also auf ein Portal — auch wenn der Aufruf über
// den Hub kam. Der Self-Canonical muss dann dem Portal folgen, nicht
// dem aufgerufenen Host (Anhang 2, E10).
View::share('webPortalContextApplied', true);
return new self(
domainKey: $domainKey,
portal: $portal,
language: app()->getLocale(),
portalValues: [$portal->value, Portal::Both->value],
domainConfig: DomainAssetContext::applyWebDomainConfig($domainKey),
);
}
}