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

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.     /**
  85.      * @return array[]
  86.      */
  87.     public static function getSubscribedEvents(): array
  88.     {
  89.         return [
  90.             TargetingEvents::PRE_RESOLVE => ['onPreResolve', -10],
  91.             KernelEvents::RESPONSE => ['onKernelResponse', -127],
  92.         ];
  93.     }
  94.     public function onPreResolve(TargetingEvent $event)
  95.     {
  96.         $request $event->getRequest();
  97.         if (!$this->requestCanDebug($request)) {
  98.             return;
  99.         }
  100.         // handle overrides from request data
  101.         $this->overrideHandler->handleRequest($request);
  102.     }
  103.     public function onKernelResponse(ResponseEvent $event)
  104.     {
  105.         if (!$event->isMainRequest()) {
  106.             return;
  107.         }
  108.         $request $event->getRequest();
  109.         if (!$this->requestCanDebug($request)) {
  110.             return;
  111.         }
  112.         // only inject toolbar if there's a visitor info
  113.         if (!$this->visitorInfoStorage->hasVisitorInfo()) {
  114.             return;
  115.         }
  116.         $document $this->documentResolver->getDocument($request);
  117.         $visitorInfo $this->visitorInfoStorage->getVisitorInfo();
  118.         $data $this->collectTemplateData($visitorInfo$document);
  119.         $overrideForm $this->overrideHandler->getForm($request);
  120.         $data['overrideForm'] = $overrideForm->createView();
  121.         $this->injectToolbar(
  122.             $event->getResponse(),
  123.             $data
  124.         );
  125.     }
  126.     private function requestCanDebug(Request $request): bool
  127.     {
  128.         if ($request->attributes->has('pimcore_targeting_debug')) {
  129.             return (bool)$request->attributes->get('pimcore_targeting_debug');
  130.         }
  131.         if (!$this->matchesPimcoreContext($requestPimcoreContextResolver::CONTEXT_DEFAULT)) {
  132.             return false;
  133.         }
  134.         // only inject toolbar for logged in admin users
  135.         $adminUser Authentication::authenticateSession($request);
  136.         if (!$adminUser) {
  137.             return false;
  138.         }
  139.         $cookieValue = (bool)$request->cookies->get('pimcore_targeting_debug');
  140.         if (!$cookieValue) {
  141.             return false;
  142.         }
  143.         $request->attributes->set('pimcore_targeting_debug'true);
  144.         return true;
  145.     }
  146.     private function collectTemplateData(VisitorInfo $visitorInfoDocument $document null)
  147.     {
  148.         $token substr(hash('sha256'uniqid((string)mt_rand(), true)), 06);
  149.         $tdc $this->targetingDataCollector;
  150.         $data = [
  151.             'token' => $token,
  152.             'visitorInfo' => $tdc->collectVisitorInfo($visitorInfo),
  153.             'targetGroups' => $tdc->collectTargetGroups($visitorInfo),
  154.             'rules' => $tdc->collectMatchedRules($visitorInfo),
  155.             'documentTargetGroup' => $tdc->collectDocumentTargetGroup($document),
  156.             'documentTargetGroups' => $tdc->collectDocumentTargetGroupMapping(),
  157.             'storage' => $tdc->collectStorage($visitorInfo),
  158.         ];
  159.         return $data;
  160.     }
  161.     private function injectToolbar(Response $response, array $data)
  162.     {
  163.         $event = new RenderToolbarEvent('@PimcoreCore/Targeting/toolbar/toolbar.html.twig'$data);
  164.         $this->eventDispatcher->dispatch($eventTargetingEvents::RENDER_TOOLBAR);
  165.         $code $this->templatingEngine->render(
  166.             $event->getTemplate(),
  167.             $event->getData()
  168.         );
  169.         $this->codeInjector->inject(
  170.             $response,
  171.             $code,
  172.             CodeInjector::SELECTOR_BODY,
  173.             CodeInjector::POSITION_END
  174.         );
  175.     }
  176. }