Skip to content

Instantly share code, notes, and snippets.

@fritzmg
Last active March 7, 2025 16:10
Show Gist options
  • Save fritzmg/e7df2804365fe676b1d88f053a234707 to your computer and use it in GitHub Desktop.
Save fritzmg/e7df2804365fe676b1d88f053a234707 to your computer and use it in GitHub Desktop.
Drop-in replacement for Contao's breadcrumb module, in order to have the correct news, event, etc. titles for the active page
<?php
// src/Controller/FrontendModule/BreadcrumbController.php
declare(strict_types=1);
namespace App\Controller\FrontendModule;
use Contao\CoreBundle\DependencyInjection\Attribute\AsFrontendModule;
use Contao\CoreBundle\Routing\ResponseContext\HtmlHeadBag\HtmlHeadBag;
use Contao\CoreBundle\Routing\ResponseContext\ResponseContextAccessor;
use Contao\CoreBundle\Routing\ScopeMatcher;
use Contao\Input;
use Contao\ModuleBreadcrumb;
use Contao\ModuleModel;
use Contao\StringUtil;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
#[AsFrontendModule('breadcrumb', 'navigationMenu', 'mod_breadcrumb', priority: 1)]
class BreadcrumbController extends ModuleBreadcrumb
{
public function __construct(
private readonly ScopeMatcher $scopeMatcher,
private readonly RequestStack $requestStack,
private readonly ResponseContextAccessor $responseContextAccessor,
) {
}
public function __invoke(Request $request, ModuleModel $model, string $section): Response
{
parent::__construct($model, $section);
if ($this->scopeMatcher->isBackendRequest($request)) {
return new Response($this->generate());
}
// Render as insert tag first
$attributeVar = '_'.$model->type.'_'.$model->id.'_render';
$mainRequest = $this->requestStack->getMainRequest();
if (!$mainRequest->attributes->has($attributeVar)) {
$mainRequest->attributes->set($attributeVar, true);
return new Response('{{insert_module::'.$model->id.'}}');
}
return new Response($this->generate());
}
protected function compile(): void
{
parent::compile();
$this->overrideActiveTitle();
}
private function overrideActiveTitle(): void
{
// Only execute on legacy reader pages
if (!Input::get('auto_item', false, true)) {
return;
}
if (!$responseContext = $this->responseContextAccessor->getResponseContext()) {
return;
}
if (!$responseContext->has(HtmlHeadBag::class)) {
return;
}
$htmlHeadBag = $responseContext->get(HtmlHeadBag::class);
if (!$htmlHeadBag->getTitle()) {
return;
}
$items = $this->Template->items;
if ($key = array_key_last($items)) {
$items[$key] = array_merge($items[$key], [
'title' => StringUtil::specialchars($htmlHeadBag->getTitle()),
'link' => $htmlHeadBag->getTitle(),
]);
}
$this->Template->items = $items;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment