'callbacks.postWatcher']) { $this->ssrHandler = new SSRHandler($interactiveNamespace, $rootElementId, $rootElementAttributes); } /** * Render the archive for `/{segment}/{termSlug}`. * * @param string $segment archive segment, e.g. `stage` * @param string $termSlug term slug within that taxonomy * * @return string */ public function show(Request $request, $segment, $termSlug) { $movedTo = PortalTaxonomies::renamedArchiveUrl((string) $segment, (string) $termSlug); if ($movedTo !== '') { wp_safe_redirect($movedTo, 301); exit; } $term = PortalTaxonomies::resolve((string) $segment, (string) $termSlug); // An unknown term is a genuine 404, not an empty archive answering 200 — // otherwise every mistyped term URL becomes an indexable blank page. if ($term === null) { return (new NotFoundController())->index($request); } // The default stage's archive lists exactly what the portal root lists, // so it is the same page under a second URL. Redirecting rather than // canonicalising keeps one address in circulation: the sidebar already // links the default stage to the root, and this catches the links that // were shared before it did. if ($segment === 'stage' && $termSlug === StageService::defaultStageSlug()) { wp_safe_redirect(PortalLocation::url(), 301); exit; } $topicsView = new TopicsView(); $topicsView->prepareArchiveData($term); $stateData = $topicsView->getState(); $viewData = $topicsView->getViewData(); SeoMeta::forArchive($term, $viewData['topics'] ?? []); return $this->ssrHandler->generateView( '/' . $segment . '/' . $termSlug, $stateData, [], $viewData ); } }