vendor/boldr/cms-bundle/src/Controller/PageController.php line 181

Open in your IDE?
  1. <?php
  2. namespace Boldr\Cms\CmsBundle\Controller;
  3. use Boldr\Cms\CmsBundle\Permalink\{ PermalinkHandlerInterface, PermalinkResolverInterface, PermalinkGeneratorInterface, PermalinkableInterface };
  4. use Boldr\Cms\CmsBundle\Homepage\HomepageProviderInterface;
  5. use Boldr\Cms\CmsBundle\Entity\{ Page, PageTranslation };
  6. use Boldr\Cms\CmsBundle\Content\Assets;
  7. use Boldr\Cms\CmsBundle\Upload\UploadStorageManager;
  8. use Boldr\Cms\CmsBundle\Presenter\Page\PagePresenter;
  9. use Boldr\Cms\CmsBundle\Repository\PageRepository;
  10. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  11. use Symfony\Component\HttpFoundation\{ Request, Response, RequestStack };
  12. use Symfony\Component\Routing\Annotation\Route;
  13. use Symfony\Contracts\Cache\TagAwareCacheInterface;
  14. class PageController extends AbstractController implements PermalinkHandlerInterface, PermalinkResolverInterface, PermalinkGeneratorInterface, HomepageProviderInterface
  15. {
  16. private PagePresenter $pagePresenter;
  17. private PageRepository $pageRepository;
  18. private UploadStorageManager $uploadStorageManager;
  19. private TagAwareCacheInterface $cache;
  20. public function __construct(PagePresenter $pagePresenter, PageRepository $pageRepository, UploadStorageManager $uploadStorageManager, TagAwareCacheInterface $cache)
  21. {
  22. $this->pagePresenter = $pagePresenter;
  23. $this->pageRepository = $pageRepository;
  24. $this->uploadStorageManager = $uploadStorageManager;
  25. $this->cache = $cache;
  26. }
  27. /**
  28. * @param Page $permalinkable
  29. */
  30. public function handlePermalink(PermalinkableInterface $permalinkable, Request $request): Response
  31. {
  32. return $this->renderPage($request, $permalinkable);
  33. }
  34. public function resolvePermalink(string $permalink, string $locale): ?PermalinkableInterface
  35. {
  36. $repoPageTranslations = $this->getDoctrine()->getRepository(PageTranslation::class);
  37. $parts = explode('/', $permalink);
  38. $page = null;
  39. foreach ($parts as $part)
  40. {
  41. $qb = $this->pageRepository->createQueryBuilder('p')
  42. ->leftJoin('p.translations', 'pt')
  43. ->andWhere('pt.locale = :locale')
  44. ->andWhere('pt.permalink = :part')
  45. ->andWhere('p.parent '. ($page === null ? 'IS NULL' : '= :parent'))
  46. ->setParameter('locale', $locale)
  47. ->setParameter('part', $part)
  48. ->setMaxResults(1)
  49. ;
  50. if ($page !== null)
  51. {
  52. $qb->setParameter('parent', $page);
  53. }
  54. $page = $qb->getQuery()->getOneOrNullResult();
  55. // If no page with this permalink can be found, return null
  56. if ($page === null)
  57. {
  58. return null;
  59. }
  60. // Otherwise continue checking for "sub" pages if $parts remain
  61. }
  62. return $page;
  63. }
  64. /**
  65. * @param Page $permalinkable
  66. */
  67. public function generatePermalink(PermalinkableInterface $permalinkable, string $locale): string
  68. {
  69. $permalinkParts = [];
  70. $page = $permalinkable;
  71. while ($page !== null)
  72. {
  73. $translation = $page->getTranslations()->get($locale);
  74. if ($translation->getPermalink() === '' || $translation->getSections() === null)
  75. {
  76. return '';
  77. }
  78. array_unshift($permalinkParts, $translation->getPermalink());
  79. $page = $page->getParent();
  80. }
  81. return join('/', $permalinkParts);
  82. }
  83. public function renderPage(Request $request, Page $page, bool $preview = false): Response
  84. {
  85. $locale = $request->getLocale();
  86. $translation = $page->getTranslations()->get($locale);
  87. if ($translation->getSections() === null && !$preview)
  88. {
  89. throw $this->createNotFoundException();
  90. }
  91. $pageView = $this->pagePresenter->createPageView($page, $locale, $preview);
  92. // JSON:
  93. if (in_array('application/json', $request->getAcceptableContentTypes()))
  94. {
  95. return $this->json($pageView);
  96. }
  97. // HTML:
  98. foreach ($pageView->getSections() as $section)
  99. {
  100. $section->getAssets();
  101. }
  102. $assets = new Assets();
  103. $assets->addAll(...array_map(
  104. fn($section) => $section->getAssets(),
  105. $pageView->getSections()
  106. ));
  107. // Add OEmbed/OpenGraph meta tags
  108. $metaTagsCacheItem = $this->cache->getItem('boldr_cms.page.meta_tags.'. $page->getId().'.'.$locale);
  109. if (!$metaTagsCacheItem->isHit() || $preview)
  110. {
  111. $metaTags = [
  112. '<meta name="twitter:card" content="'. ($page->getPrimaryImage() ? 'summary_large_image' : 'summary') .'" />',
  113. '<meta property="og:url" content="'. $request->getUri() .'" />',
  114. '<meta property="og:type" content="article" />'
  115. ];
  116. if ($pageView->getDescription())
  117. {
  118. $metaTags[] = '<meta name="description" property="og:description" content="'.htmlentities($pageView->getDescription()).'" />';
  119. }
  120. if ($page->getPrimaryImage())
  121. {
  122. $baseUrl = $request->getSchemeAndHttpHost().$request->getBasePath();
  123. $imageUrl = $this->uploadStorageManager->getImageUrl($page->getPrimaryImage(), $baseUrl, 'medium');
  124. $metaTags[] = '<meta property="og:image" content="'. $imageUrl .'" />';
  125. }
  126. $metaTagsHtml = join("\n", $metaTags);
  127. if (!$preview)
  128. {
  129. $metaTagsCacheItem->set($metaTagsHtml);
  130. $metaTagsCacheItem->tag('boldr_cms.page.'. $page->getId());
  131. $this->cache->saveDeferred($metaTagsCacheItem);
  132. }
  133. }
  134. else
  135. {
  136. $metaTagsHtml = $metaTagsCacheItem->get();
  137. }
  138. $assets->addHtmlContentToHead($metaTagsHtml);
  139. $template = $pageView->getPageLayout()->getTemplate();
  140. $variables = $pageView->getPageLayout()->getVariables();
  141. return $this->render($template, [
  142. 'page' => $pageView,
  143. 'assets' => $assets,
  144. ] + $variables);
  145. }
  146. public function handleHomepage(Request $request, string $homepageId): Response
  147. {
  148. $repoPage = $this->getDoctrine()->getRepository(Page::class);
  149. $page = $repoPage->createQueryBuilder('p')
  150. ->select('p, t')
  151. ->leftJoin('p.translations', 't')
  152. ->where('p.id = ?1')
  153. ->setParameter(1, $homepageId)
  154. ->getQuery()
  155. ->getOneOrNullResult();
  156. if ($page === null)
  157. {
  158. throw new \Exception('Homepage misconfigured');
  159. }
  160. $locale = $request->getLocale();
  161. // Save the permalinkable in a request attribute
  162. $request->attributes->set('_permalinkable', $page);
  163. return $this->renderPage($request, $page);
  164. }
  165. }