vendor/presta/sitemap-bundle/EventListener/RouteAnnotationEventListener.php line 73

Open in your IDE?
  1. <?php
  2. /**
  3.  * This file is part of the PrestaSitemapBundle package.
  4.  *
  5.  * (c) PrestaConcept <www.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\SitemapPopulateEvent;
  12. use Presta\SitemapBundle\Sitemap\Url\UrlConcrete;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
  15. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  16. use Symfony\Component\Routing\Route;
  17. use Symfony\Component\Routing\RouteCollection;
  18. use Symfony\Component\Routing\RouterInterface;
  19. /**
  20.  * this listener allows you to use annotations to include routes in the Sitemap, just like
  21.  * https://github.com/dreipunktnull/DpnXmlSitemapBundle
  22.  *
  23.  * supported parameters are:
  24.  *
  25.  *  lastmod: a text string that can be parsed by \DateTime
  26.  *  changefreq: a text string that matches a constant defined in UrlConcrete
  27.  *  priority: a number between 0 and 1
  28.  *
  29.  * if you don't want to specify these parameters, you can simply use
  30.  * Route("/", name="homepage", options={"sitemap" = true })
  31.  *
  32.  * @author Tony Piper (tpiper@tpiper.com)
  33.  */
  34. class RouteAnnotationEventListener implements EventSubscriberInterface
  35. {
  36.     /**
  37.      * @var RouterInterface
  38.      */
  39.     protected $router;
  40.     /**
  41.      * @var string
  42.      */
  43.     private $defaultSection;
  44.     /**
  45.      * @param RouterInterface $router
  46.      * @param string          $defaultSection
  47.      */
  48.     public function __construct(RouterInterface $router$defaultSection)
  49.     {
  50.         $this->router $router;
  51.         $this->defaultSection $defaultSection;
  52.     }
  53.     /**
  54.      * @inheritdoc
  55.      */
  56.     public static function getSubscribedEvents()
  57.     {
  58.         return array(
  59.             SitemapPopulateEvent::ON_SITEMAP_POPULATE => ['registerRouteAnnotation'0],
  60.         );
  61.     }
  62.     /**
  63.      * @param SitemapPopulateEvent $event
  64.      */
  65.     public function registerRouteAnnotation(SitemapPopulateEvent $event)
  66.     {
  67.         $section $event->getSection();
  68.         if (is_null($section) || $section === $this->defaultSection) {
  69.             $this->addUrlsFromRoutes($event);
  70.         }
  71.     }
  72.     /**
  73.      * @param SitemapPopulateEvent $event
  74.      *
  75.      * @throws \InvalidArgumentException
  76.      */
  77.     private function addUrlsFromRoutes(SitemapPopulateEvent $event)
  78.     {
  79.         $collection $this->getRouteCollection();
  80.         $container $event->getUrlContainer();
  81.         foreach ($collection->all() as $name => $route) {
  82.             $options $this->getOptions($name$route);
  83.             if (!$options) {
  84.                 continue;
  85.             }
  86.             $section $event->getSection() ?: $this->defaultSection;
  87.             if (isset($options['section'])) {
  88.                 $section $options['section'];
  89.             }
  90.             $container->addUrl(
  91.                 $this->getUrlConcrete($name$options),
  92.                 $section
  93.             );
  94.         }
  95.     }
  96.     /**
  97.      * @return RouteCollection
  98.      */
  99.     protected function getRouteCollection()
  100.     {
  101.         return $this->router->getRouteCollection();
  102.     }
  103.     /**
  104.      * @param string $name
  105.      * @param Route  $route
  106.      *
  107.      * @return array
  108.      * @throws \InvalidArgumentException
  109.      */
  110.     public function getOptions($nameRoute $route)
  111.     {
  112.         $option $route->getOption('sitemap');
  113.         if ($option === null) {
  114.             return null;
  115.         }
  116.         if (is_string($option)) {
  117.             $decoded json_decode($optiontrue);
  118.             if (!json_last_error() && is_array($decoded)) {
  119.                 $option $decoded;
  120.             }
  121.         }
  122.         if (!is_array($option) && !is_bool($option)) {
  123.             $bool filter_var($optionFILTER_VALIDATE_BOOLEANFILTER_NULL_ON_FAILURE);
  124.             if (null === $bool) {
  125.                 throw new \InvalidArgumentException(
  126.                     sprintf(
  127.                         'The sitemap option must be of type "boolean" or "array", got "%s"',
  128.                         $option
  129.                     )
  130.                 );
  131.             }
  132.             $option $bool;
  133.         }
  134.         if (!$option) {
  135.             return null;
  136.         }
  137.         $options = [
  138.             'lastmod' => null,
  139.             'changefreq' => null,
  140.             'priority' => null,
  141.         ];
  142.         if (is_array($option)) {
  143.             $options array_merge($options$option);
  144.         }
  145.         if (is_string($options['lastmod'])) {
  146.             try {
  147.                 $options['lastmod'] = new \DateTime($options['lastmod']);
  148.             } catch (\Exception $e) {
  149.                 throw new \InvalidArgumentException(
  150.                     sprintf(
  151.                         'The route %s has an invalid value "%s" specified for the "lastmod" option',
  152.                         $name,
  153.                         $options['lastmod']
  154.                     ),
  155.                     0,
  156.                     $e
  157.                 );
  158.             }
  159.         }
  160.         return $options;
  161.     }
  162.     /**
  163.      * @param string $name    Route name
  164.      * @param array  $options Node options
  165.      *
  166.      * @return UrlConcrete
  167.      * @throws \InvalidArgumentException
  168.      */
  169.     protected function getUrlConcrete($name$options)
  170.     {
  171.         try {
  172.             return new UrlConcrete(
  173.                 $this->getRouteUri($name),
  174.                 $options['lastmod'],
  175.                 $options['changefreq'],
  176.                 $options['priority']
  177.             );
  178.         } catch (\Exception $e) {
  179.             throw new \InvalidArgumentException(
  180.                 sprintf(
  181.                     'Invalid argument for route "%s": %s',
  182.                     $name,
  183.                     $e->getMessage()
  184.                 ),
  185.                 0,
  186.                 $e
  187.             );
  188.         }
  189.     }
  190.     /**
  191.      * @param string $name   Route name
  192.      * @param array  $params Route additional parameters
  193.      *
  194.      * @return string
  195.      * @throws \InvalidArgumentException
  196.      */
  197.     protected function getRouteUri($name$params = array())
  198.     {
  199.         // If the route needs additional parameters, we can't add it
  200.         try {
  201.             return $this->router->generate($name$paramsUrlGeneratorInterface::ABSOLUTE_URL);
  202.         } catch (MissingMandatoryParametersException $e) {
  203.             throw new \InvalidArgumentException(
  204.                 sprintf(
  205.                     'The route "%s" cannot have the sitemap option because it requires parameters other than "%s"',
  206.                     $name,
  207.                     implode('", "'array_keys($params))
  208.                 ),
  209.                 0,
  210.                 $e
  211.             );
  212.         }
  213.     }
  214. }