vendor/sulu/sulu/src/Sulu/Bundle/WebsiteBundle/Controller/WebsiteController.php line 110

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of Sulu.
  4. *
  5. * (c) Sulu GmbH
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace Sulu\Bundle\WebsiteBundle\Controller;
  11. use Sulu\Bundle\HttpCacheBundle\CacheLifetime\CacheLifetimeEnhancerInterface;
  12. use Sulu\Bundle\PreviewBundle\Preview\Preview;
  13. use Sulu\Bundle\WebsiteBundle\Resolver\ParameterResolverInterface;
  14. use Sulu\Component\Content\Compat\StructureInterface;
  15. use Sulu\Component\Webspace\Analyzer\RequestAnalyzerInterface;
  16. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\Response;
  19. use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
  20. /**
  21. * Basic class to render Website from phpcr content.
  22. */
  23. abstract class WebsiteController extends AbstractController
  24. {
  25. /**
  26. * Returns a rendered structure.
  27. *
  28. * @param StructureInterface $structure The structure, which has been loaded for rendering
  29. * @param array $attributes Additional attributes, which will be passed to twig
  30. * @param bool $preview Defines if the site is rendered in preview mode
  31. * @param bool $partial Defines if only the content block of the template should be rendered
  32. *
  33. * @return Response
  34. */
  35. protected function renderStructure(
  36. StructureInterface $structure,
  37. $attributes = [],
  38. $preview = false,
  39. $partial = false
  40. ) {
  41. $request = $this->getRequest();
  42. // extract format twig file
  43. if (!$preview) {
  44. $requestFormat = $request->getRequestFormat();
  45. } else {
  46. $requestFormat = 'html';
  47. }
  48. $viewTemplate = $structure->getView() . '.' . $requestFormat . '.twig';
  49. if (!$this->container->get('twig')->getLoader()->exists($viewTemplate)) {
  50. throw new NotAcceptableHttpException(\sprintf('Page does not exist in "%s" format.', $requestFormat));
  51. }
  52. // get attributes to render template
  53. $data = $this->getAttributes($attributes, $structure, $preview);
  54. // if partial render only content block else full page
  55. if ($partial) {
  56. $content = $this->renderBlockView(
  57. $viewTemplate,
  58. 'content',
  59. $data
  60. );
  61. } elseif ($preview) {
  62. $content = $this->renderPreview(
  63. $viewTemplate,
  64. $data
  65. );
  66. } else {
  67. $content = $this->renderView(
  68. $viewTemplate,
  69. $data
  70. );
  71. }
  72. $response = new Response($content);
  73. // we need to set the content type ourselves here
  74. // else symfony will use the accept header of the client and the page could be cached with false content-type
  75. // see following symfony issue: https://github.com/symfony/symfony/issues/35694
  76. $mimeType = $request->getMimeType($requestFormat);
  77. if ($mimeType) {
  78. $response->headers->set('Content-Type', $mimeType);
  79. }
  80. if (!$preview && $this->getCacheTimeLifeEnhancer()) {
  81. $this->getCacheTimeLifeEnhancer()->enhance($response, $structure);
  82. }
  83. return $response;
  84. }
  85. /**
  86. * Generates attributes.
  87. *
  88. * @param mixed[] $attributes
  89. * @param bool $preview
  90. *
  91. * @return mixed[]
  92. */
  93. protected function getAttributes($attributes, ?StructureInterface $structure = null, $preview = false)
  94. {
  95. return $this->container->get('sulu_website.resolver.parameter')->resolve(
  96. $attributes,
  97. $this->container->get('sulu_core.webspace.request_analyzer'),
  98. $structure,
  99. $preview
  100. );
  101. }
  102. /**
  103. * Returns rendered part of template specified by block.
  104. *
  105. * @param string $view
  106. * @param string $block
  107. * @param array<string, mixed> $parameters
  108. */
  109. protected function renderBlockView($view, $block, $parameters = []): string
  110. {
  111. $twig = $this->container->get('twig');
  112. $parameters = $twig->mergeGlobals($parameters);
  113. $template = $twig->load($view);
  114. $level = \ob_get_level();
  115. \ob_start();
  116. try {
  117. $rendered = $template->renderBlock($block, $parameters);
  118. \ob_end_clean();
  119. return $rendered;
  120. } catch (\Exception $e) {
  121. while (\ob_get_level() > $level) {
  122. \ob_end_clean();
  123. }
  124. throw $e;
  125. }
  126. }
  127. protected function renderPreview(string $view, array $parameters = []): string
  128. {
  129. $parameters['previewParentTemplate'] = $view;
  130. $parameters['previewContentReplacer'] = Preview::CONTENT_REPLACER;
  131. return $this->renderView('@SuluWebsite/Preview/preview.html.twig', $parameters);
  132. }
  133. /**
  134. * Returns the current request from the request stack.
  135. *
  136. * @return Request
  137. *
  138. * @deprecated will be remove with 2.0
  139. */
  140. public function getRequest()
  141. {
  142. return $this->container->get('request_stack')->getCurrentRequest();
  143. }
  144. protected function getCacheTimeLifeEnhancer(): ?CacheLifetimeEnhancerInterface
  145. {
  146. if (!$this->container->has('sulu_http_cache.cache_lifetime.enhancer')) {
  147. return null;
  148. }
  149. /** @var CacheLifetimeEnhancerInterface $cacheLifetimeEnhancer */
  150. $cacheLifetimeEnhancer = $this->container->get('sulu_http_cache.cache_lifetime.enhancer');
  151. return $cacheLifetimeEnhancer;
  152. }
  153. public static function getSubscribedServices(): array
  154. {
  155. $subscribedServices = parent::getSubscribedServices();
  156. $subscribedServices['sulu_website.resolver.parameter'] = ParameterResolverInterface::class;
  157. $subscribedServices['sulu_core.webspace.request_analyzer'] = RequestAnalyzerInterface::class;
  158. $subscribedServices['sulu_http_cache.cache_lifetime.enhancer'] = '?' . CacheLifetimeEnhancerInterface::class;
  159. return $subscribedServices;
  160. }
  161. }