vendor/presta/sitemap-bundle/src/EventListener/RouteAnnotationEventListener.php line 82

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the PrestaSitemapBundle package.
  4. *
  5. * (c) PrestaConcept <https://prestaconcept.net>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Presta\SitemapBundle\EventListener;
  11. use Presta\SitemapBundle\Event\SitemapAddUrlEvent;
  12. use Presta\SitemapBundle\Event\SitemapPopulateEvent;
  13. use Presta\SitemapBundle\Routing\RouteOptionParser;
  14. use Presta\SitemapBundle\Service\UrlContainerInterface;
  15. use Presta\SitemapBundle\Sitemap\Url\UrlConcrete;
  16. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
  19. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  20. use Symfony\Component\Routing\RouterInterface;
  21. /**
  22. * Listen to "presta_sitemap.populate" event.
  23. * Populate sitemap with configured static routes.
  24. *
  25. * @phpstan-import-type RouteOptions from RouteOptionParser
  26. */
  27. class RouteAnnotationEventListener implements EventSubscriberInterface
  28. {
  29. /**
  30. * @var RouterInterface
  31. */
  32. protected $router;
  33. /**
  34. * @var EventDispatcherInterface
  35. */
  36. private $dispatcher;
  37. /**
  38. * @var string
  39. */
  40. private $defaultSection;
  41. public function __construct(
  42. RouterInterface $router,
  43. EventDispatcherInterface $eventDispatcher,
  44. string $defaultSection
  45. ) {
  46. $this->router = $router;
  47. $this->dispatcher = $eventDispatcher;
  48. $this->defaultSection = $defaultSection;
  49. }
  50. /**
  51. * @inheritdoc
  52. */
  53. public static function getSubscribedEvents(): array
  54. {
  55. return [
  56. SitemapPopulateEvent::class => ['registerRouteAnnotation', 0],
  57. ];
  58. }
  59. /**
  60. * @param SitemapPopulateEvent $event
  61. */
  62. public function registerRouteAnnotation(SitemapPopulateEvent $event): void
  63. {
  64. $this->addUrlsFromRoutes($event->getUrlContainer(), $event->getSection());
  65. }
  66. /**
  67. * @param UrlContainerInterface $container
  68. * @param string|null $section
  69. *
  70. * @throws \InvalidArgumentException
  71. */
  72. private function addUrlsFromRoutes(UrlContainerInterface $container, ?string $section): void
  73. {
  74. $collection = $this->router->getRouteCollection();
  75. foreach ($collection->all() as $name => $route) {
  76. $options = RouteOptionParser::parse($name, $route);
  77. if (!$options) {
  78. continue;
  79. }
  80. $routeSection = $options['section'] ?? $this->defaultSection;
  81. if ($section !== null && $routeSection !== $section) {
  82. continue;
  83. }
  84. $event = new SitemapAddUrlEvent($name, $options, $this->router);
  85. $this->dispatcher->dispatch($event, SitemapAddUrlEvent::NAME);
  86. if (!$event->shouldBeRegistered()) {
  87. continue;
  88. }
  89. $container->addUrl(
  90. $event->getUrl() ?? $this->getUrlConcrete($name, $options),
  91. $routeSection
  92. );
  93. }
  94. }
  95. /**
  96. * @param string $name Route name
  97. * @param RouteOptions $options Node options
  98. *
  99. * @return UrlConcrete
  100. * @throws \InvalidArgumentException
  101. */
  102. protected function getUrlConcrete(string $name, array $options): UrlConcrete
  103. {
  104. try {
  105. return new UrlConcrete(
  106. $this->getRouteUri($name),
  107. $options['lastmod'],
  108. $options['changefreq'],
  109. $options['priority']
  110. );
  111. } catch (\Exception $e) {
  112. throw new \InvalidArgumentException(
  113. sprintf(
  114. 'Invalid argument for route "%s": %s',
  115. $name,
  116. $e->getMessage()
  117. ),
  118. 0,
  119. $e
  120. );
  121. }
  122. }
  123. /**
  124. * @param string $name Route name
  125. * @param array<string, mixed> $params Route additional parameters
  126. *
  127. * @return string
  128. * @throws \InvalidArgumentException
  129. */
  130. protected function getRouteUri(string $name, array $params = []): string
  131. {
  132. // If the route needs additional parameters, we can't add it
  133. try {
  134. return $this->router->generate($name, $params, UrlGeneratorInterface::ABSOLUTE_URL);
  135. } catch (MissingMandatoryParametersException $e) {
  136. throw new \InvalidArgumentException(
  137. sprintf(
  138. 'The route "%s" cannot have the sitemap option because it requires parameters other than "%s"',
  139. $name,
  140. implode('", "', array_keys($params))
  141. ),
  142. 0,
  143. $e
  144. );
  145. }
  146. }
  147. }