<?php
namespace App\Controller\Page;
use App\Component\Configuration\Util\Config;
use App\Entity\HeroConfiguration;
use App\Entity\OgImage;
use App\Entity\Route;
use App\Event\PageEvent;
use App\EventListener\FeatureFlagListener;
use App\Model\Tealium\Base as TealiumBase;
use App\Renderer\Page as PageRenderer;
use App\Util\Breadcrumb;
use App\Util\CookiescriptHelper;
use App\Util\Seo;
use Flagception\Manager\FeatureManagerInterface;
use FOS\HttpCacheBundle\Http\SymfonyResponseTagger;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
/**
* A custom controller to handle a content specified by a route.
*/
class RoutingController extends AbstractController
{
private PageRenderer $pageRenderer;
private Breadcrumb $breadcrumb;
private Seo $seo;
private EventDispatcherInterface $dispatcher;
private FeatureManagerInterface $featureManager;
public function __construct(
PageRenderer $pageRenderer,
Breadcrumb $breadcrumb,
Seo $seo,
EventDispatcherInterface $dispatcher,
FeatureManagerInterface $featureManager
) {
$this->pageRenderer = $pageRenderer;
$this->breadcrumb = $breadcrumb;
$this->seo = $seo;
$this->dispatcher = $dispatcher;
$this->featureManager = $featureManager;
}
public function resolve(Request $request, Config $config, SymfonyResponseTagger $responseTagger): Response
{
/** @var Route $route */
$route = $this->getDoctrine()->getRepository(Route::class)->findOneBy([
'name' => $request->get('_route'),
]);
if (!$page = $route->getPage()) {
throw $this->createNotFoundException();
}
$responseTagger->addTags(['pages', 'pages-'.$page->getId()]);
$this->getDoctrine()->getManager()->getFilters()->disable('softdeleteable');
if ($page->isDeleted()) {
throw $this->createNotFoundException();
}
$this->getDoctrine()->getManager()->getFilters()->enable('softdeleteable');
$this->seo->setSeoInformationForPage([], $page, (new OgImage())->setImage($config->get('site_open_graph_image')));
$cacheable = true;
$this->dispatcher->dispatch(new PageEvent(page: $page, request: $request), PageEvent::PAGE_BEFORE_RENDER);
if (str_contains($page->getBody(), '{open_applicant_form}')) {
$cacheable = false;
$body = $this->forward('App\Controller\Page\ApplicantSnippetController:snippetAction')->getContent();
$page->setBody(str_replace('{open_applicant_form}', $body, $page->getBody()));
}
if (str_contains($page->getBody(), '{product_invoice_form')) {
preg_match('{product_invoice_form:?(\d*)}', $page->getBody(), $matches);
if (!empty($matches[1])) {
$cacheable = false;
$body = $this->forward(
ProductController::class.':snippet',
['id' => $matches[1]]
)->getContent();
$page->setBody(str_replace('{'.$matches[0].'}', $body, $page->getBody()));
}
}
if (str_contains($page->getBody(), '{products_by_tag:')) {
preg_match('{products_by_tag:?(\d*)}', $page->getBody(), $matches);
if (!empty($matches[1])) {
$cacheable = false;
$body = $this->forward(
ProductsController::class.':snippet',
['tagId' => $matches[1]]
)->getContent();
$page->setBody(str_replace('{'.$matches[0].'}', $body, $page->getBody()));
}
}
$hero = null;
if ($this->featureManager->isActive(FeatureFlagListener::FEATURE_HERO) && $page->getHeroConfiguration() instanceof HeroConfiguration) {
$hero = $this->renderView(
'@default/pages/hero_configuration.html.twig',
[
'heroConfiguration' => $page->getHeroConfiguration(),
]
);
}
$response = $this->render(
'@default/pages/pages_index.html.twig',
[
'header' => $this->pageRenderer->getHeader($page),
'footer' => $this->pageRenderer->getFooter(),
'page' => $page,
'breadcrumbs' => $this->breadcrumb->getBreadcrumbsForPage($page),
'locale' => $route->getLocale(),
'hero' => $hero,
'tealium_data' => TealiumBase::createForPage($request, $page, $route)->toJson(),
'tealium_push_directly' => true,
]
);
$response->setContent(
CookiescriptHelper::cookiefyMarkup($response->getContent())
);
if ('404_page' === $page->getAlias()) {
$response->setStatusCode(Response::HTTP_NOT_FOUND);
}
if ('500_page' === $page->getAlias()) {
$response->setStatusCode(Response::HTTP_INTERNAL_SERVER_ERROR);
}
if (!$cacheable) {
$response
->setMaxAge(0)
->setSharedMaxAge(0)
->setPrivate()
->headers->addCacheControlDirective('must-revalidate')
;
}
return $response;
}
}