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

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.      * @param RouterInterface $router
  42.      */
  43.     public function __construct(RouterInterface $router)
  44.     {
  45.         $this->router $router;
  46.     }
  47.     /**
  48.      * @inheritdoc
  49.      */
  50.     public static function getSubscribedEvents()
  51.     {
  52.         return array(
  53.             SitemapPopulateEvent::ON_SITEMAP_POPULATE => ['registerRouteAnnotation'0],
  54.         );
  55.     }
  56.     /**
  57.      * @param SitemapPopulateEvent $event
  58.      */
  59.     public function registerRouteAnnotation(SitemapPopulateEvent $event)
  60.     {
  61.         $section $event->getSection();
  62.         if (is_null($section) || $section == 'default') {
  63.             $this->addUrlsFromRoutes($event);
  64.         }
  65.     }
  66.     /**
  67.      * @param SitemapPopulateEvent $event
  68.      *
  69.      * @throws \InvalidArgumentException
  70.      */
  71.     private function addUrlsFromRoutes(SitemapPopulateEvent $event)
  72.     {
  73.         $collection $this->getRouteCollection();
  74.         $container $event->getUrlContainer();
  75.         foreach ($collection->all() as $name => $route) {
  76.             $options $this->getOptions($name$route);
  77.             if (!$options) {
  78.                 continue;
  79.             }
  80.             $section $event->getSection() ?: 'default';
  81.             if (isset($options['section'])) {
  82.                 $section $options['section'];
  83.             }
  84.             $container->addUrl(
  85.                 $this->getUrlConcrete($name$options),
  86.                 $section
  87.             );
  88.         }
  89.     }
  90.     /**
  91.      * @return RouteCollection
  92.      */
  93.     protected function getRouteCollection()
  94.     {
  95.         return $this->router->getRouteCollection();
  96.     }
  97.     /**
  98.      * @param string $name
  99.      * @param Route  $route
  100.      *
  101.      * @return array
  102.      * @throws \InvalidArgumentException
  103.      */
  104.     public function getOptions($nameRoute $route)
  105.     {
  106.         $option $route->getOption('sitemap');
  107.         if ($option === null) {
  108.             return null;
  109.         }
  110.         if (is_string($option)) {
  111.             $decoded json_decode($optiontrue);
  112.             if (!json_last_error() && is_array($decoded)) {
  113.                 $option $decoded;
  114.             }
  115.         }
  116.         if (!is_array($option) && !is_bool($option)) {
  117.             $bool filter_var($optionFILTER_VALIDATE_BOOLEANFILTER_NULL_ON_FAILURE);
  118.             if (null === $bool) {
  119.                 throw new \InvalidArgumentException(
  120.                     sprintf(
  121.                         'The sitemap option must be of type "boolean" or "array", got "%s"',
  122.                         $option
  123.                     )
  124.                 );
  125.             }
  126.             $option $bool;
  127.         }
  128.         if (!$option) {
  129.             return null;
  130.         }
  131.         $options = [
  132.             'lastmod' => null,
  133.             'changefreq' => null,
  134.             'priority' => null,
  135.         ];
  136.         if (is_array($option)) {
  137.             $options array_merge($options$option);
  138.         }
  139.         if (is_string($options['lastmod'])) {
  140.             try {
  141.                 $options['lastmod'] = new \DateTime($options['lastmod']);
  142.             } catch (\Exception $e) {
  143.                 throw new \InvalidArgumentException(
  144.                     sprintf(
  145.                         'The route %s has an invalid value "%s" specified for the "lastmod" option',
  146.                         $name,
  147.                         $options['lastmod']
  148.                     ),
  149.                     0,
  150.                     $e
  151.                 );
  152.             }
  153.         }
  154.         return $options;
  155.     }
  156.     /**
  157.      * @param string $name    Route name
  158.      * @param array  $options Node options
  159.      *
  160.      * @return UrlConcrete
  161.      * @throws \InvalidArgumentException
  162.      */
  163.     protected function getUrlConcrete($name$options)
  164.     {
  165.         try {
  166.             return new UrlConcrete(
  167.                 $this->getRouteUri($name),
  168.                 $options['lastmod'],
  169.                 $options['changefreq'],
  170.                 $options['priority']
  171.             );
  172.         } catch (\Exception $e) {
  173.             throw new \InvalidArgumentException(
  174.                 sprintf(
  175.                     'Invalid argument for route "%s": %s',
  176.                     $name,
  177.                     $e->getMessage()
  178.                 ),
  179.                 0,
  180.                 $e
  181.             );
  182.         }
  183.     }
  184.     /**
  185.      * @param string $name   Route name
  186.      * @param array  $params Route additional parameters
  187.      *
  188.      * @return string
  189.      * @throws \InvalidArgumentException
  190.      */
  191.     protected function getRouteUri($name$params = array())
  192.     {
  193.         // If the route needs additional parameters, we can't add it
  194.         try {
  195.             return $this->router->generate($name$paramsUrlGeneratorInterface::ABSOLUTE_URL);
  196.         } catch (MissingMandatoryParametersException $e) {
  197.             throw new \InvalidArgumentException(
  198.                 sprintf(
  199.                     'The route "%s" cannot have the sitemap option because it requires parameters other than "%s"',
  200.                     $name,
  201.                     implode('", "'array_keys($params))
  202.                 ),
  203.                 0,
  204.                 $e
  205.             );
  206.         }
  207.     }
  208. }