vendor/pimcore/pimcore/lib/Targeting/EventListener/ToolbarListener.php line 106

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4.  * Pimcore
  5.  *
  6.  * This source file is available under two different licenses:
  7.  * - GNU General Public License version 3 (GPLv3)
  8.  * - Pimcore Commercial License (PCL)
  9.  * Full copyright and license information is available in
  10.  * LICENSE.md which is distributed with this source code.
  11.  *
  12.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  13.  *  @license    http://www.pimcore.org/license     GPLv3 and PCL
  14.  */
  15. namespace Pimcore\Targeting\EventListener;
  16. use Pimcore\Bundle\CoreBundle\EventListener\Traits\PimcoreContextAwareTrait;
  17. use Pimcore\Event\Targeting\RenderToolbarEvent;
  18. use Pimcore\Event\Targeting\TargetingEvent;
  19. use Pimcore\Event\TargetingEvents;
  20. use Pimcore\Http\Request\Resolver\DocumentResolver;
  21. use Pimcore\Http\Request\Resolver\PimcoreContextResolver;
  22. use Pimcore\Http\Response\CodeInjector;
  23. use Pimcore\Model\Document;
  24. use Pimcore\Targeting\Debug\OverrideHandler;
  25. use Pimcore\Targeting\Debug\TargetingDataCollector;
  26. use Pimcore\Targeting\Model\VisitorInfo;
  27. use Pimcore\Targeting\VisitorInfoStorageInterface;
  28. use Pimcore\Tool\Authentication;
  29. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  30. use Symfony\Component\HttpFoundation\Request;
  31. use Symfony\Component\HttpFoundation\Response;
  32. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  33. use Symfony\Component\HttpKernel\KernelEvents;
  34. use Symfony\Component\Templating\EngineInterface;
  35. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  36. class ToolbarListener implements EventSubscriberInterface
  37. {
  38.     use PimcoreContextAwareTrait;
  39.     /**
  40.      * @var VisitorInfoStorageInterface
  41.      */
  42.     private $visitorInfoStorage;
  43.     /**
  44.      * @var DocumentResolver
  45.      */
  46.     private $documentResolver;
  47.     /**
  48.      * @var TargetingDataCollector
  49.      */
  50.     private $targetingDataCollector;
  51.     /**
  52.      * @var OverrideHandler
  53.      */
  54.     private $overrideHandler;
  55.     /**
  56.      * @var EventDispatcherInterface
  57.      */
  58.     private $eventDispatcher;
  59.     /**
  60.      * @var EngineInterface
  61.      */
  62.     private $templatingEngine;
  63.     /**
  64.      * @var CodeInjector
  65.      */
  66.     private $codeInjector;
  67.     public function __construct(
  68.         VisitorInfoStorageInterface $visitorInfoStorage,
  69.         DocumentResolver $documentResolver,
  70.         TargetingDataCollector $targetingDataCollector,
  71.         OverrideHandler $overrideHandler,
  72.         EventDispatcherInterface $eventDispatcher,
  73.         EngineInterface $templatingEngine,
  74.         CodeInjector $codeInjector
  75.     ) {
  76.         $this->visitorInfoStorage $visitorInfoStorage;
  77.         $this->documentResolver $documentResolver;
  78.         $this->targetingDataCollector $targetingDataCollector;
  79.         $this->overrideHandler $overrideHandler;
  80.         $this->eventDispatcher $eventDispatcher;
  81.         $this->templatingEngine $templatingEngine;
  82.         $this->codeInjector $codeInjector;
  83.     }
  84.     public static function getSubscribedEvents()
  85.     {
  86.         return [
  87.             TargetingEvents::PRE_RESOLVE => ['onPreResolve', -10],
  88.             KernelEvents::RESPONSE => ['onKernelResponse', -127],
  89.         ];
  90.     }
  91.     public function onPreResolve(TargetingEvent $event)
  92.     {
  93.         $request $event->getRequest();
  94.         if (!$this->requestCanDebug($request)) {
  95.             return;
  96.         }
  97.         // handle overrides from request data
  98.         $this->overrideHandler->handleRequest($request);
  99.     }
  100.     public function onKernelResponse(ResponseEvent $event)
  101.     {
  102.         if (!$event->isMainRequest()) {
  103.             return;
  104.         }
  105.         $request $event->getRequest();
  106.         if (!$this->requestCanDebug($request)) {
  107.             return;
  108.         }
  109.         // only inject toolbar if there's a visitor info
  110.         if (!$this->visitorInfoStorage->hasVisitorInfo()) {
  111.             return;
  112.         }
  113.         $document $this->documentResolver->getDocument($request);
  114.         $visitorInfo $this->visitorInfoStorage->getVisitorInfo();
  115.         $data $this->collectTemplateData($visitorInfo$document);
  116.         $overrideForm $this->overrideHandler->getForm($request);
  117.         $data['overrideForm'] = $overrideForm->createView();
  118.         $this->injectToolbar(
  119.             $event->getResponse(),
  120.             $data
  121.         );
  122.     }
  123.     private function requestCanDebug(Request $request): bool
  124.     {
  125.         if ($request->attributes->has('pimcore_targeting_debug')) {
  126.             return (bool)$request->attributes->get('pimcore_targeting_debug');
  127.         }
  128.         if (!$this->matchesPimcoreContext($requestPimcoreContextResolver::CONTEXT_DEFAULT)) {
  129.             return false;
  130.         }
  131.         // only inject toolbar for logged in admin users
  132.         $adminUser Authentication::authenticateSession($request);
  133.         if (!$adminUser) {
  134.             return false;
  135.         }
  136.         $cookieValue = (bool)$request->cookies->get('pimcore_targeting_debug'false);
  137.         if (!$cookieValue) {
  138.             return false;
  139.         }
  140.         $request->attributes->set('pimcore_targeting_debug'true);
  141.         return true;
  142.     }
  143.     private function collectTemplateData(VisitorInfo $visitorInfoDocument $document null)
  144.     {
  145.         $token substr(hash('sha256'uniqid((string)mt_rand(), true)), 06);
  146.         $tdc $this->targetingDataCollector;
  147.         $data = [
  148.             'token' => $token,
  149.             'visitorInfo' => $tdc->collectVisitorInfo($visitorInfo),
  150.             'targetGroups' => $tdc->collectTargetGroups($visitorInfo),
  151.             'rules' => $tdc->collectMatchedRules($visitorInfo),
  152.             'documentTargetGroup' => $tdc->collectDocumentTargetGroup($document),
  153.             'documentTargetGroups' => $tdc->collectDocumentTargetGroupMapping(),
  154.             'storage' => $tdc->collectStorage($visitorInfo),
  155.         ];
  156.         return $data;
  157.     }
  158.     private function injectToolbar(Response $response, array $data)
  159.     {
  160.         $event = new RenderToolbarEvent('@PimcoreCore/Targeting/toolbar/toolbar.html.twig'$data);
  161.         $this->eventDispatcher->dispatch($eventTargetingEvents::RENDER_TOOLBAR);
  162.         $code $this->templatingEngine->render(
  163.             $event->getTemplate(),
  164.             $event->getData()
  165.         );
  166.         $this->codeInjector->inject(
  167.             $response,
  168.             $code,
  169.             CodeInjector::SELECTOR_BODY,
  170.             CodeInjector::POSITION_END
  171.         );
  172.     }
  173. }