vendor/shopware/core/System/SalesChannel/SalesChannel/ContextSwitchRoute.php line 123

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\System\SalesChannel\SalesChannel;
  3. use Shopware\Core\Checkout\Cart\CartException;
  4. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Validation\EntityExists;
  7. use Shopware\Core\Framework\Log\Package;
  8. use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
  9. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  10. use Shopware\Core\Framework\Validation\DataValidationDefinition;
  11. use Shopware\Core\Framework\Validation\DataValidator;
  12. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextPersister;
  13. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
  14. use Shopware\Core\System\SalesChannel\ContextTokenResponse;
  15. use Shopware\Core\System\SalesChannel\Event\SalesChannelContextSwitchEvent;
  16. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  19. #[Route(defaults: ['_routeScope' => ['store-api']])]
  20. #[Package('core')]
  21. class ContextSwitchRoute extends AbstractContextSwitchRoute
  22. {
  23.     private const SHIPPING_METHOD_ID SalesChannelContextService::SHIPPING_METHOD_ID;
  24.     private const PAYMENT_METHOD_ID SalesChannelContextService::PAYMENT_METHOD_ID;
  25.     private const BILLING_ADDRESS_ID SalesChannelContextService::BILLING_ADDRESS_ID;
  26.     private const SHIPPING_ADDRESS_ID SalesChannelContextService::SHIPPING_ADDRESS_ID;
  27.     private const COUNTRY_ID SalesChannelContextService::COUNTRY_ID;
  28.     private const STATE_ID SalesChannelContextService::COUNTRY_STATE_ID;
  29.     private const CURRENCY_ID SalesChannelContextService::CURRENCY_ID;
  30.     private const LANGUAGE_ID SalesChannelContextService::LANGUAGE_ID;
  31.     /**
  32.      * @var SalesChannelContextPersister
  33.      */
  34.     protected $contextPersister;
  35.     /**
  36.      * @var DataValidator
  37.      */
  38.     protected $validator;
  39.     /**
  40.      * @internal
  41.      */
  42.     public function __construct(
  43.         DataValidator $validator,
  44.         SalesChannelContextPersister $contextPersister,
  45.         private readonly EventDispatcherInterface $eventDispatcher
  46.     ) {
  47.         $this->contextPersister $contextPersister;
  48.         $this->validator $validator;
  49.     }
  50.     public function getDecorated(): AbstractContextSwitchRoute
  51.     {
  52.         throw new DecorationPatternException(self::class);
  53.     }
  54.     #[Route(path'/store-api/context'name'store-api.switch-context'methods: ['PATCH'])]
  55.     public function switchContext(RequestDataBag $dataSalesChannelContext $context): ContextTokenResponse
  56.     {
  57.         $definition = new DataValidationDefinition('context_switch');
  58.         $parameters $data->only(
  59.             self::SHIPPING_METHOD_ID,
  60.             self::PAYMENT_METHOD_ID,
  61.             self::BILLING_ADDRESS_ID,
  62.             self::SHIPPING_ADDRESS_ID,
  63.             self::COUNTRY_ID,
  64.             self::STATE_ID,
  65.             self::CURRENCY_ID,
  66.             self::LANGUAGE_ID
  67.         );
  68.         $addressCriteria = new Criteria();
  69.         if ($context->getCustomer()) {
  70.             $addressCriteria->addFilter(new EqualsFilter('customer_address.customerId'$context->getCustomer()->getId()));
  71.         } else {
  72.             // do not allow to set address ids if the customer is not logged in
  73.             if (isset($parameters[self::SHIPPING_ADDRESS_ID])) {
  74.                 throw CartException::customerNotLoggedIn();
  75.             }
  76.             if (isset($parameters[self::BILLING_ADDRESS_ID])) {
  77.                 throw CartException::customerNotLoggedIn();
  78.             }
  79.         }
  80.         $currencyCriteria = new Criteria();
  81.         $currencyCriteria->addFilter(
  82.             new EqualsFilter('currency.salesChannels.id'$context->getSalesChannel()->getId())
  83.         );
  84.         $languageCriteria = new Criteria();
  85.         $languageCriteria->addFilter(
  86.             new EqualsFilter('language.salesChannels.id'$context->getSalesChannel()->getId())
  87.         );
  88.         $paymentMethodCriteria = new Criteria();
  89.         $paymentMethodCriteria->addFilter(
  90.             new EqualsFilter('payment_method.salesChannels.id'$context->getSalesChannel()->getId())
  91.         );
  92.         $shippingMethodCriteria = new Criteria();
  93.         $shippingMethodCriteria->addFilter(
  94.             new EqualsFilter('shipping_method.salesChannels.id'$context->getSalesChannel()->getId())
  95.         );
  96.         $definition
  97.             ->add(self::LANGUAGE_ID, new EntityExists(['entity' => 'language''context' => $context->getContext(), 'criteria' => $languageCriteria]))
  98.             ->add(self::CURRENCY_ID, new EntityExists(['entity' => 'currency''context' => $context->getContext(), 'criteria' => $currencyCriteria]))
  99.             ->add(self::SHIPPING_METHOD_ID, new EntityExists(['entity' => 'shipping_method''context' => $context->getContext(), 'criteria' => $shippingMethodCriteria]))
  100.             ->add(self::PAYMENT_METHOD_ID, new EntityExists(['entity' => 'payment_method''context' => $context->getContext(), 'criteria' => $paymentMethodCriteria]))
  101.             ->add(self::BILLING_ADDRESS_ID, new EntityExists(['entity' => 'customer_address''context' => $context->getContext(), 'criteria' => $addressCriteria]))
  102.             ->add(self::SHIPPING_ADDRESS_ID, new EntityExists(['entity' => 'customer_address''context' => $context->getContext(), 'criteria' => $addressCriteria]))
  103.             ->add(self::COUNTRY_ID, new EntityExists(['entity' => 'country''context' => $context->getContext()]))
  104.             ->add(self::STATE_ID, new EntityExists(['entity' => 'country_state''context' => $context->getContext()]))
  105.         ;
  106.         $this->validator->validate($parameters$definition);
  107.         $customer $context->getCustomer();
  108.         $this->contextPersister->save(
  109.             $context->getToken(),
  110.             $parameters,
  111.             $context->getSalesChannel()->getId(),
  112.             $customer && empty($context->getPermissions()) ? $customer->getId() : null
  113.         );
  114.         // Language was switched - Check new Domain
  115.         $changeUrl $this->checkNewDomain($parameters$context);
  116.         $event = new SalesChannelContextSwitchEvent($context$data);
  117.         $this->eventDispatcher->dispatch($event);
  118.         return new ContextTokenResponse($context->getToken(), $changeUrl);
  119.     }
  120.     /**
  121.      * @param array<mixed> $parameters
  122.      */
  123.     private function checkNewDomain(array $parametersSalesChannelContext $context): ?string
  124.     {
  125.         if (
  126.             !isset($parameters[self::LANGUAGE_ID])
  127.             || $parameters[self::LANGUAGE_ID] === $context->getLanguageId()
  128.         ) {
  129.             return null;
  130.         }
  131.         $domains $context->getSalesChannel()->getDomains();
  132.         if ($domains === null) {
  133.             return null;
  134.         }
  135.         $langDomain $domains->filterByProperty('languageId'$parameters[self::LANGUAGE_ID])->first();
  136.         if ($langDomain === null) {
  137.             return null;
  138.         }
  139.         return $langDomain->getUrl();
  140.     }
  141. }