custom/plugins/PickwareDhl/src/SalesChannelContext/Subscriber/SynchronizeSalesChannelContextsSubscriber.php line 128

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright (c) Pickware GmbH. All rights reserved.
  4.  * This file is part of software that is released under a proprietary license.
  5.  * You must not copy, modify, distribute, make publicly available, or execute
  6.  * its contents or parts thereof without express permission by the copyright
  7.  * holder, unless otherwise permitted by law.
  8.  */
  9. declare(strict_types=1);
  10. namespace Pickware\PickwareDhl\SalesChannelContext\Subscriber;
  11. use Pickware\DalBundle\EntityManager;
  12. use Pickware\PickwareDhl\SalesChannelContext\Model\SalesChannelApiContextDefinition;
  13. use Pickware\PickwareDhl\SalesChannelContext\Model\SalesChannelApiContextEntity;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  16. use Shopware\Core\System\SalesChannel\Event\SalesChannelContextSwitchEvent;
  17. use Shopware\Storefront\Event\StorefrontRenderEvent;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. class SynchronizeSalesChannelContextsSubscriber implements EventSubscriberInterface
  20. {
  21.     public const PAYLOAD_KEY_DELIMITER '__';
  22.     public const SYNCHRONIZATION_PREFIX 'pickware' self::PAYLOAD_KEY_DELIMITER;
  23.     public const PICKWARE_SALES_CHANNEL_CONTEXT_EXTENSION_NAME 'pickwareSalesChannelContext';
  24.     private EntityManager $entityManager;
  25.     public function __construct(EntityManager $entityManager)
  26.     {
  27.         $this->entityManager $entityManager;
  28.     }
  29.     public static function getSubscribedEvents(): array
  30.     {
  31.         return [
  32.             SalesChannelContextSwitchEvent::class => 'onSalesChannelContextSwitched',
  33.             StorefrontRenderEvent::class => 'onStorefrontPageRendered',
  34.         ];
  35.     }
  36.     /**
  37.      * This method persists all request parameters in the PickwareSalesChannelContext that were passed to the
  38.      * ContextSwitchRoute (where the event is thrown) and that start with 'pickware__'.
  39.      *
  40.      * The following example highlights the style in which the parameters are persisted:
  41.      *  Request Parameters:
  42.      *      'pickware__some_package__some_key': 'some-value'
  43.      *      'pickware__some_package__some_other_key': 'a-second-value'
  44.      *      'pickware__some_other_package__some_key': 'a-third-value'
  45.      *  Value persisted in the pickware sales channel context:
  46.      *      [
  47.      *          'some_package' => [
  48.      *              'some_key' => 'some-value',
  49.      *              'some_other_key' => 'a-second-value'
  50.      *          ],
  51.      *          'some_other_package' => [
  52.      *              'some_key' => 'a-third-value'
  53.      *          ]
  54.      *      ]
  55.      */
  56.     public function onSalesChannelContextSwitched(SalesChannelContextSwitchEvent $event): void
  57.     {
  58.         $requestPayload $event->getRequestDataBag()->all();
  59.         $flattenedPickwarePayload array_filter($requestPayload, fn (string $key) => str_starts_with($keyself::SYNCHRONIZATION_PREFIX), ARRAY_FILTER_USE_KEY);
  60.         if (count($flattenedPickwarePayload) === 0) {
  61.             return;
  62.         }
  63.         $pickwarePayload array_merge_recursive(...array_map(function (string $key) use ($flattenedPickwarePayload) {
  64.             $keyWithoutPrefix str_replace(self::SYNCHRONIZATION_PREFIX''$key);
  65.             return $this->unflattenKeyPayload(explode(self::PAYLOAD_KEY_DELIMITER$keyWithoutPrefix), $flattenedPickwarePayload[$key]);
  66.         }, array_keys($flattenedPickwarePayload)));
  67.         /** @var SalesChannelApiContextEntity $existingPickwareSalesChannelContext */
  68.         $existingPickwareSalesChannelContext $this->entityManager->findOneBy(
  69.             SalesChannelApiContextDefinition::class,
  70.             (new Criteria())->addFilter(new EqualsFilter('salesChannelContextToken'$event->getSalesChannelContext()->getToken())),
  71.             $event->getContext(),
  72.         );
  73.         $this->entityManager->upsert(
  74.             SalesChannelApiContextDefinition::class,
  75.             [[
  76.                 'salesChannelContextToken' => $event->getSalesChannelContext()->getToken(),
  77.                 'payload' => array_replace_recursive(
  78.                     $existingPickwareSalesChannelContext $existingPickwareSalesChannelContext->getPayload() : [],
  79.                     $pickwarePayload,
  80.                 ),
  81.             ],
  82.             ],
  83.             $event->getContext(),
  84.         );
  85.     }
  86.     /**
  87.      * Returns a nested array, where each keyPart is used as key once in the order they are contained in the parameter.
  88.      * Example:
  89.      *  Parameters:
  90.      *      keyParts => ['dhl_some_package', 'some_content_key']
  91.      *      value => 'some-value'
  92.      *  Returns:
  93.      *      [
  94.      *          'dhl_some_package' => [
  95.      *              'some_content_key' => 'some-value'
  96.      *          ]
  97.      *      ]
  98.      *
  99.      * @return array[]|string[]
  100.      */
  101.     private function unflattenKeyPayload(array $keyPartsstring $value): array
  102.     {
  103.         if (count($keyParts) === 0) {
  104.             return [$value];
  105.         }
  106.         if (count($keyParts) === 1) {
  107.             return [$keyParts[0] => $value];
  108.         }
  109.         return [$keyParts[0] => $this->unflattenKeyPayload(array_slice($keyParts1), $value)];
  110.     }
  111.     public function onStorefrontPageRendered(StorefrontRenderEvent $event): void
  112.     {
  113.         /** @var SalesChannelApiContextEntity $pickwareSalesChannelContext */
  114.         $pickwareSalesChannelContext $this->entityManager->findOneBy(
  115.             SalesChannelApiContextDefinition::class,
  116.             (new Criteria())->addFilter(new EqualsFilter('salesChannelContextToken'$event->getSalesChannelContext()->getToken())),
  117.             $event->getContext(),
  118.         );
  119.         $event->getSalesChannelContext()->addExtension(
  120.             self::PICKWARE_SALES_CHANNEL_CONTEXT_EXTENSION_NAME,
  121.             $pickwareSalesChannelContext,
  122.         );
  123.     }
  124. }