vendor/boldr/cms-bundle/src/Controller/SitemapController.php line 38

Open in your IDE?
  1. <?php
  2. namespace Boldr\Cms\CmsBundle\Controller;
  3. use Boldr\Cms\CmsBundle\Controller\PermalinkController;
  4. use Boldr\Cms\CmsBundle\Permalink\PermalinkableInterface;
  5. use Psr\Cache\CacheItemInterface;
  6. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  7. use Symfony\Component\Routing\Annotation\Route;
  8. use Symfony\Component\HttpFoundation\{ Request, Response, ResponseHeaderBag};
  9. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  10. use Symfony\Contracts\Cache\CacheInterface;
  11. class SitemapController extends AbstractController
  12. {
  13. private iterable $sitemapLinkProviders;
  14. private PermalinkController $permalinkController;
  15. public function __construct(iterable $sitemapLinkProviders, PermalinkController $permalinkController)
  16. {
  17. $this->sitemapLinkProviders = $sitemapLinkProviders;
  18. $this->permalinkController = $permalinkController;
  19. }
  20. /** @Route("/robots.txt", name="cms_robots") */
  21. public function robots()
  22. {
  23. $response = new Response('Sitemap: '. $this->generateUrl('cms_sitemap', [], UrlGeneratorInterface::ABSOLUTE_URL) . PHP_EOL);
  24. $response->headers->set('Content-Type', 'text/plain');
  25. return $response;
  26. }
  27. /**
  28. * @Route("/sitemap.xml", name="cms_sitemap")
  29. */
  30. public function sitemap(Request $request, CacheInterface $cache)
  31. {
  32. $base = $request->getSchemeAndHttpHost().$request->getBaseUrl();
  33. $hash = md5($base);
  34. $cachePath = $this->getParameter('kernel.cache_dir').'/boldrcms-sitemap-'.$hash.'.xml';
  35. if (!file_exists($cachePath) || time() - filemtime($cachePath) > 3600)
  36. {
  37. $this->generateSitemap($base, $cachePath);
  38. }
  39. $response = $this->file($cachePath, 'sitemap.xml', ResponseHeaderBag::DISPOSITION_INLINE);
  40. $response->headers->set('Content-Type', 'application/xml');
  41. return $response;
  42. }
  43. private function generateSitemap(string $base, string $path): void
  44. {
  45. $xml = '<?xml version="1.0" encoding="UTF-8"?>';
  46. $xml .= '<?xml-stylesheet type="text/xsl" href="/bundles/boldrcms/sitemap.xsl"?>';
  47. $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">';
  48. $localeBaseUrls = $this->getParameter('boldr_cms.locale_base_urls');
  49. $currentLocale = false;
  50. foreach ($localeBaseUrls as $locale => $localeBaseUrl)
  51. {
  52. if (is_array($localeBaseUrl) ? in_array($base, $localeBaseUrl, true) : $localeBaseUrl === $base)
  53. {
  54. $currentLocale = $locale;
  55. break;
  56. }
  57. }
  58. $currentLocale = $currentLocale === false ? $this->getParameter('kernel.default_locale') : $currentLocale;
  59. foreach ($this->sitemapLinkProviders as $sitemapLinkProvider)
  60. {
  61. foreach ($sitemapLinkProvider->getSitemapLinks() as $link)
  62. {
  63. $priority = $link->getPriority();
  64. $lastModified = $link->getLastModified();
  65. $changeFrequency = $link->getChangeFrequency();
  66. $url = $link->getUrl();
  67. $urlsXml = '';
  68. if ($url instanceof PermalinkableInterface)
  69. {
  70. $urls = [];
  71. foreach ($this->getParameter('boldr_cms.enabled_locales') as $locale) {
  72. $permalink = $this->permalinkController->generate($url, $locale);
  73. if ($permalink)
  74. {
  75. $urls[$locale] = $permalink;
  76. }
  77. }
  78. $url = $urls;
  79. }
  80. if (is_array($url))
  81. {
  82. foreach ($url as $locale => $localizedUrl)
  83. {
  84. $localizedBase = $localeBaseUrls[$locale] ?? $base;
  85. if (is_array($localizedBase))
  86. {
  87. $localizedBase = $localizedBase[0];
  88. }
  89. if ($locale !== $currentLocale)
  90. {
  91. $urlsXml .= '<xhtml:link rel="alternate" hreflang="'.self::encodeString($locale).'" href="'.self::encodeString($localizedBase.$localizedUrl).'"/>';
  92. }
  93. }
  94. $defaultUrl = $url[$currentLocale] ?? current($url);
  95. }
  96. else
  97. {
  98. $defaultUrl = $url;
  99. }
  100. $xml .= '<url>'.
  101. '<loc>'.self::encodeString($base.$defaultUrl).'</loc>'.
  102. ($lastModified !== null
  103. ? '<lastmod>'.self::encodeString($link->getLastModified()->format('Y-m-d\TH:i:s+00:00')).'</lastmod>'
  104. : ''
  105. ).
  106. $urlsXml.
  107. ($changeFrequency !== null
  108. ? '<changefreq>'.self::encodeString($link->getChangeFrequency()).'</changefreq>'
  109. : ''
  110. ).
  111. ($priority != 0.5
  112. ? '<priority>'.$link->getPriority().'</priority>'
  113. : ''
  114. ).
  115. '</url>'.PHP_EOL;
  116. }
  117. }
  118. $xml .= '</urlset>';
  119. file_put_contents($path, $xml);
  120. }
  121. private static function encodeString(string $str): string
  122. {
  123. return strtr($str, [
  124. '<' => '&lt;',
  125. '&' => '&amp;',
  126. '>' => '&gt;',
  127. '"' => '&quot;',
  128. '\'' => '&apos;'
  129. ]);
  130. }
  131. }