vendor/pimcore/direct-edit/src/Service/PublishService.php line 57

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under following license:
  6.  * - Pimcore Commercial License (PCL)
  7.  *
  8.  *  @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  9.  *  @license    http://www.pimcore.org/license     PCL
  10.  */
  11. namespace Pimcore\Bundle\DirectEditBundle\Service;
  12. use Lcobucci\JWT\Builder;
  13. use Lcobucci\JWT\Configuration;
  14. use Lcobucci\JWT\Signer\Hmac\Sha256;
  15. use Lcobucci\JWT\Signer\Key;
  16. use Pimcore\Bundle\DirectEditBundle\Exception\DirectEditException;
  17. use Pimcore\Bundle\DirectEditBundle\Model\Mercure\Subscription;
  18. use Psr\Log\LoggerInterface;
  19. use Symfony\Component\DependencyInjection\ContainerInterface;
  20. use Symfony\Component\HttpClient\HttpClient;
  21. use Symfony\Component\Mercure\Jwt\StaticJwtProvider;
  22. use Symfony\Component\Mercure\Publisher;
  23. use Symfony\Component\Mercure\Update;
  24. class PublishService
  25. {
  26.     private $httpClient;
  27.     /**
  28.      * @var Publisher
  29.      */
  30.     private $publisher;
  31.     /**
  32.      * @var LoggerInterface
  33.      */
  34.     private $logger;
  35.     /**
  36.      * @var string
  37.      */
  38.     private $jwt;
  39.     /**
  40.      * @var MercureUrlService
  41.      */
  42.     private $mercureUrlService;
  43.     public function __construct(ContainerInterface $containerLoggerInterface $directEditLoggerMercureUrlService $mercureUrlService)
  44.     {
  45.         $this->httpClient HttpClient::create();
  46.         $this->mercureUrlService $mercureUrlService;
  47.         $mercureConfig $container->getParameter('mercure');
  48.         $jwtKey = @$mercureConfig['hub']['jwt_key'];
  49.         if (empty($jwtKey)) {
  50.             throw new DirectEditException('You must configure "mercure.hub.jwt_key" in your parameters.');
  51.         }
  52.         $subscriptionPayload = [
  53.             'subscribe' => ['*']
  54.         ];
  55.         $this->jwt $this->buildJwt($jwtKey$subscriptionPayload);
  56.         $publishPayload = [
  57.                 'publish' => ['*']
  58.         ];
  59.         $jwtPublishToken $this->buildJwt($jwtKey$publishPayload);
  60.         $publisher = new Publisher(
  61.             $this->mercureUrlService->getServerSideUrl(), //see documentation
  62.             new StaticJwtProvider($jwtPublishToken));
  63.         $this->publisher $publisher;
  64.         $this->logger $directEditLogger;
  65.     }
  66.     private function buildJwt(string $jwtKey, array $payLoad): string
  67.     {
  68.         if (class_exists('Lcobucci\JWT\Token\Builder')) {
  69.             $configuration Configuration::forSymmetricSigner// @phpstan-ignore-line
  70.                 new Sha256(),
  71.                 Key\InMemory::plainText($jwtKey)                // @phpstan-ignore-line
  72.             );
  73.             $token $configuration->builder()->withClaim('mercure'$payLoad)->getToken($configuration->signer(), $configuration->signingKey())->toString();
  74.         } else {
  75.             $token = (new Builder())->withClaim('mercure'$payLoad// @phpstan-ignore-line
  76.                 ->getToken(new Sha256(), new Key($jwtKey));                // @phpstan-ignore-line
  77.         }
  78.         return $token;
  79.     }
  80.     public function sendUpdate(string $topic, array $data)
  81.     {
  82.         $this->logger->debug('Send update via mercure.',
  83.             [
  84.                 'topic' => $topic,
  85.                 'data' => $data
  86.             ]);
  87.         $update = new Update($topicjson_encode($data), false);
  88.         $this->publisher->__invoke($update);
  89.     }
  90.     /**
  91.      * @throws \Exception
  92.      */
  93.     public function discoverSubscriptions(?string $topicbool $filterByActive false): array
  94.     {
  95.         $urlTopicSelector '';
  96.         /*
  97.             token selector doesn't work in current Mercure version (also tested in postman)
  98.             $urlTopicSelector = '/'.urlencode($topic);
  99.         */
  100.         try {
  101.             $response $this->httpClient->request('GET',
  102.                 $this->mercureUrlService->getServerSideUrl() . '/subscriptions'.$urlTopicSelector, [
  103.                     'headers' => [
  104.                         'Authorization' => 'Bearer '.$this->jwt
  105.                     ]
  106.                 ])->getContent();
  107.             $subscriptionList = [];
  108.             $subscriptionData json_decode($responsetrue);
  109.             if (isset($subscriptionData['subscriptions'])) {
  110.                 foreach ($subscriptionData['subscriptions'] as $subscription) {
  111.                     $subscriptionObject $this->subscriptionAsObject($subscription);
  112.                     if ($topic && strpos($subscriptionObject->getTopic(), $topic) !== 0) {
  113.                         continue;
  114.                     }
  115.                     if ($filterByActive && !$subscriptionObject->isActive()) {
  116.                         continue;
  117.                     }
  118.                     $subscriptionList[] = $subscriptionObject;
  119.                 }
  120.             }
  121.             return $subscriptionList;
  122.         } catch (\Exception $e) {
  123.             $this->logger->alert('DiscoverSubscriptions: '.$e->getMessage());
  124.             return [];
  125.         }
  126.     }
  127.     private function subscriptionAsObject(array $subscription): Subscription
  128.     {
  129.         $subscriptionObject = new Subscription();
  130.         $subscriptionObject
  131.             ->setType($subscription['type'])
  132.             ->setId($subscription['id'])
  133.             ->setTopic($subscription['topic'])
  134.             ->setSubscriber($subscription['subscriber'])
  135.             ->setActive($subscription['active'])
  136.         ;
  137.         return $subscriptionObject;
  138.     }
  139. }