vendor/sulu/sulu/src/Sulu/Bundle/WebsiteBundle/EventListener/AppendAnalyticsListener.php line 86

  1. <?php
  2. /*
  3.  * This file is part of Sulu.
  4.  *
  5.  * (c) Sulu GmbH
  6.  *
  7.  * This source file is subject to the MIT license that is bundled
  8.  * with this source code in the file LICENSE.
  9.  */
  10. namespace Sulu\Bundle\WebsiteBundle\EventListener;
  11. use Sulu\Bundle\WebsiteBundle\Entity\AnalyticsInterface;
  12. use Sulu\Bundle\WebsiteBundle\Entity\AnalyticsRepositoryInterface;
  13. use Sulu\Component\Webspace\Analyzer\RequestAnalyzerInterface;
  14. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  15. use Twig\Environment;
  16. /**
  17.  * Appends analytics scripts into body.
  18.  */
  19. class AppendAnalyticsListener
  20. {
  21.     private static $positions = [
  22.         'head-open' => [
  23.             'regex' => '/(<head [^>]*>|<head>)/',
  24.             'sprintf' => '$1%s',
  25.         ],
  26.         'head-close' => [
  27.             'regex' => '/<\/head>/',
  28.             'sprintf' => '%s</head>',
  29.         ],
  30.         'body-open' => [
  31.             'regex' => '/(<body [^>]*>|<body>)/',
  32.             'sprintf' => '$1%s',
  33.         ],
  34.         'body-close' => [
  35.             'regex' => '/<\/body>/',
  36.             'sprintf' => '%s</body>',
  37.         ],
  38.     ];
  39.     /**
  40.      * @var Environment
  41.      */
  42.     private $engine;
  43.     /**
  44.      * @var RequestAnalyzerInterface
  45.      */
  46.     private $requestAnalyzer;
  47.     /**
  48.      * @var AnalyticsRepositoryInterface
  49.      */
  50.     private $analyticsRepository;
  51.     /**
  52.      * @var string
  53.      */
  54.     private $environment;
  55.     /**
  56.      * @var bool
  57.      */
  58.     private $preview;
  59.     public function __construct(
  60.         Environment $engine,
  61.         RequestAnalyzerInterface $requestAnalyzer,
  62.         AnalyticsRepositoryInterface $analyticsRepository,
  63.         $environment,
  64.         bool $preview false
  65.     ) {
  66.         $this->engine $engine;
  67.         $this->requestAnalyzer $requestAnalyzer;
  68.         $this->analyticsRepository $analyticsRepository;
  69.         $this->environment $environment;
  70.         $this->preview $preview;
  71.     }
  72.     /**
  73.      * Appends analytics scripts into body.
  74.      */
  75.     public function onResponse(ResponseEvent $event)
  76.     {
  77.         if (!$event->isMainRequest()
  78.             || $this->preview
  79.         ) {
  80.             return;
  81.         }
  82.         $response $event->getResponse();
  83.         if (!== \strpos($response->headers->get('Content-Type'), 'text/html')
  84.             || !$response->getContent()
  85.             || null === $this->requestAnalyzer->getPortalInformation()
  86.         ) {
  87.             return;
  88.         }
  89.         $portalUrl $this->requestAnalyzer->getAttribute('urlExpression');
  90.         if (!$portalUrl) {
  91.             return;
  92.         }
  93.         $analyticsArray $this->analyticsRepository->findByUrl(
  94.             $portalUrl,
  95.             $this->requestAnalyzer->getPortalInformation()->getWebspaceKey(),
  96.             $this->environment
  97.         );
  98.         $analyticsContent = [];
  99.         foreach ($analyticsArray as $analytics) {
  100.             $analyticsContent $this->generateAnalyticsContent($analyticsContent$analytics);
  101.         }
  102.         $response $event->getResponse();
  103.         $response->setContent($this->setAnalyticsContent($response->getContent(), $analyticsContent));
  104.     }
  105.     /**
  106.      * Generate content for each possible position.
  107.      *
  108.      * @return array
  109.      */
  110.     protected function generateAnalyticsContent(array $analyticsContentAnalyticsInterface $analytics)
  111.     {
  112.         foreach (\array_keys(self::$positions) as $position) {
  113.             $template '@SuluWebsite/Analytics/' $analytics->getType() . '/' $position '.html.twig';
  114.             if (!$this->engine->getLoader()->exists($template)) {
  115.                 continue;
  116.             }
  117.             $content $this->engine->render($template, ['analytics' => $analytics]);
  118.             if (!$content) {
  119.                 continue;
  120.             }
  121.             if (!\array_key_exists($position$analyticsContent)) {
  122.                 $analyticsContent[$position] = '';
  123.             }
  124.             $analyticsContent[$position] .= $content;
  125.         }
  126.         return $analyticsContent;
  127.     }
  128.     /**
  129.      * Set the generated content for each position.
  130.      *
  131.      * @param string $responseContent
  132.      *
  133.      * @return string
  134.      */
  135.     protected function setAnalyticsContent($responseContent, array $analyticsContent)
  136.     {
  137.         foreach ($analyticsContent as $id => $content) {
  138.             if (!$content) {
  139.                 continue;
  140.             }
  141.             $responseContent \preg_replace(
  142.                 self::$positions[$id]['regex'],
  143.                 \sprintf(self::$positions[$id]['sprintf'], $content),
  144.                 $responseContent
  145.             );
  146.         }
  147.         return $responseContent;
  148.     }
  149. }