web: Portal-Inhalte sind auf dem Hub nicht mehr erreichbar (Anhang 2, E10)
Kategorien, Jahresarchive, Meldungen und Newsrooms liefen auch unter pressekonto.com — die Ausgabe-Routen gelten für alle Hosts, und der Portal-Kontext fällt dort auf businessportal24 zurück. Jetzt 301 auf das Portal. Meldung und Newsroom folgen ihrem eigenen Portal, nicht einer festen Vorgabe; bei Doppelveröffentlichung (gleicher Slug auf beiden Portalen) gewinnt die Erstquelle, sonst endete die Weiterleitung auf der Kopie. Kategorie, Archiv und Suche gibt es auf beiden Portalen — dort entscheidet canonical.portal_only_host. Bewusst nicht weitergeleitet wird ein unbekannter Slug (sonst 301 in ein 404) und alles, was kein GET ist (ein 301 auf POST verliert die Anfrage — Newsroom beanspruchen und Share-Zählung laufen weiter). Query-Parameter bleiben erhalten. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
4c17a17254
commit
24c1bbf500
5 changed files with 222 additions and 28 deletions
|
|
@ -2,33 +2,82 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\Company;
|
||||
use App\Models\PressRelease;
|
||||
use App\Support\StaticPageCanonical;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Portalseiten auf dem Hub (Anhang 2, E10): Preise, Veröffentlichen,
|
||||
* Newsrooms und Suche gibt es nur auf den Portalen. Unter pressekonto.com
|
||||
* wurden sie bisher trotzdem ausgeliefert — mit dem Branding von
|
||||
* businessportal24, weil der Portal-Kontext dort darauf zurückfällt. Statt
|
||||
* einer Seite mit fremdem Namen unter fremder Domain: 301 auf das führende
|
||||
* Portal.
|
||||
* Portalseiten und Portal-Inhalte auf dem Hub (Anhang 2, E10).
|
||||
*
|
||||
* Die Ausgabe-Routen (`/{edition}/…`) gelten für alle Hosts, deshalb waren
|
||||
* Preise, Veröffentlichen, Newsrooms, Suche, Kategorien, Jahresarchive,
|
||||
* Meldungen und Newsrooms auch unter pressekonto.com erreichbar — mit dem
|
||||
* Branding von businessportal24, weil der Portal-Kontext auf dem Hub darauf
|
||||
* zurückfällt. Der Hub ist der Publisher-Bereich und hat diese Inhalte
|
||||
* nicht; sie gehören auf das Portal.
|
||||
*
|
||||
* Ziel ist bei Meldung und Newsroom das Portal des Eintrags selbst (bei
|
||||
* `both` und bei den übrigen Seiten das Standard-Portal). Ist der Eintrag
|
||||
* unbekannt, wird NICHT weitergeleitet — dann läuft wie bisher die 404-
|
||||
* bzw. Tombstone-Behandlung, statt den Besucher auf eine Adresse zu
|
||||
* schicken, die es auch dort nicht gibt.
|
||||
*/
|
||||
class RedirectPortalOnlyPagesFromHub
|
||||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if (! str_contains($request->getHost(), 'pressekonto')) {
|
||||
// Nur lesende Aufrufe: ein 301 auf ein POST (Newsroom beanspruchen,
|
||||
// Share-Zählung) würde die Anfrage verlieren.
|
||||
if (! str_contains($request->getHost(), 'pressekonto') || ! $request->isMethod('GET')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$base = StaticPageCanonical::portalOnlyRedirect($request->route()?->getName());
|
||||
$routeName = $request->route()?->getName();
|
||||
$base = StaticPageCanonical::portalOnlyRedirect($routeName)
|
||||
?? $this->contentPortalBase($request, $routeName);
|
||||
|
||||
if ($base === null) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
return redirect($base.$request->getPathInfo(), 301);
|
||||
return redirect($base.$request->getRequestUri(), 301);
|
||||
}
|
||||
|
||||
/**
|
||||
* Portal-Basis für eine Inhaltsadresse, oder null, wenn die Route keine
|
||||
* Inhaltsroute ist oder der Eintrag nicht existiert.
|
||||
*/
|
||||
private function contentPortalBase(Request $request, ?string $routeName): ?string
|
||||
{
|
||||
if ($routeName === null || ! in_array($routeName, (array) config('canonical.portal_only_content_routes', []), true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$slug = $request->route()?->parameter('slug');
|
||||
|
||||
// Kategorie und Jahresarchiv gibt es auf beiden Portalen — dort
|
||||
// entscheidet das Standard-Portal.
|
||||
if (! is_string($slug) || ! in_array($routeName, ['release.detail', 'newsroom', 'newsroom.claim'], true)) {
|
||||
return StaticPageCanonical::defaultPortalBase();
|
||||
}
|
||||
|
||||
// Entfernte und depublizierte Einträge zählen mit: ihre Adresse
|
||||
// liefert auf dem Portal einen Tombstone, und der gehört dorthin.
|
||||
//
|
||||
// Bei Doppelveröffentlichung tragen beide Fassungen denselben Slug —
|
||||
// dann gewinnt die Erstquelle (ohne `canonical_press_release_id`),
|
||||
// damit die Weiterleitung nicht auf der Kopie endet.
|
||||
$portal = $routeName === 'release.detail'
|
||||
? PressRelease::query()->withoutGlobalScopes()
|
||||
->where('slug', $slug)
|
||||
->orderByRaw('canonical_press_release_id is null desc')
|
||||
->orderBy('id')
|
||||
->value('portal')
|
||||
: Company::query()->withoutGlobalScopes()->where('slug', $slug)->orderBy('id')->value('portal');
|
||||
|
||||
return $portal === null ? null : StaticPageCanonical::portalBaseFor((string) ($portal->value ?? $portal));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue