custom/plugins/EsmComputer/src/Storefront/Subscriber/CheckoutSubscriber.php line 101

Open in your IDE?
  1. <?php /** @noinspection JsonEncodingApiUsageInspection */
  2. declare(strict_types=1);
  3. namespace EsmComputer\Storefront\Subscriber;
  4. use Shopware\Core\Checkout\Cart\Event\BeforeLineItemRemovedEvent;
  5. use Shopware\Core\Checkout\Cart\Exception\CustomerNotLoggedInException;
  6. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  7. use Shopware\Core\Checkout\Customer\Event\GuestCustomerRegisterEvent;
  8. use Shopware\Core\Checkout\Customer\SalesChannel\AbstractListAddressRoute;
  9. use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
  10. use Shopware\Core\Checkout\Shipping\ShippingMethodEntity;
  11. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  15. use Shopware\Core\Framework\Struct\ArrayStruct;
  16. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  17. use Shopware\Core\System\Country\SalesChannel\AbstractCountryRoute;
  18. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
  19. use Shopware\Core\System\SalesChannel\Event\SalesChannelContextSwitchEvent;
  20. use Shopware\Core\System\SalesChannel\SalesChannel\ContextSwitchRoute;
  21. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  22. use Shopware\Core\System\Salutation\SalesChannel\AbstractSalutationRoute;
  23. use Shopware\Core\System\Salutation\SalutationCollection;
  24. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  25. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  26. use Swag\CmsExtensions\Form\Aggregate\FormGroup\FormGroupEntity;
  27. use Swag\CmsExtensions\Form\Aggregate\FormGroupField\FormGroupFieldEntity;
  28. use Swag\CmsExtensions\Form\Event\CustomFormEvent;
  29. use Swag\CmsExtensions\Form\FormEntity;
  30. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  31. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  32. use Symfony\Component\HttpFoundation\Request;
  33. use Symfony\Component\HttpFoundation\Session\Session;
  34. use function array_key_exists;
  35. use function dd;
  36. use function dump;
  37. use function hash;
  38. use function json_decode;
  39. use function json_encode;
  40. class CheckoutSubscriber implements EventSubscriberInterface
  41. {
  42.     private EntityRepository $formRepository;
  43.     private Session $session;
  44.     private EventDispatcherInterface $eventDispatcher;
  45.     private AbstractCountryRoute $countryRoute;
  46.     private AbstractSalutationRoute $salutationRoute;
  47.     private AbstractListAddressRoute $addressRoute;
  48.     private CartService $cartService;
  49.     private EntityRepository $paymentMethodRepository;
  50.     private EntityRepository $shippingMethodRepository;
  51.     public function __construct(
  52.         EntityRepository $formRepository,
  53.         Session $session,
  54.         EventDispatcherInterface $eventDispatcher,
  55.         AbstractCountryRoute $countryRoute,
  56.         AbstractSalutationRoute $salutationRoute,
  57.         AbstractListAddressRoute $addressRoute,
  58.         CartService $cartService,
  59.         EntityRepository $paymentMethodRepository,
  60.         EntityRepository $shippingMethodRepository
  61.     )
  62.     {
  63.         $this->formRepository $formRepository;
  64.         $this->session $session;
  65.         $this->eventDispatcher $eventDispatcher;
  66.         $this->countryRoute $countryRoute;
  67.         $this->salutationRoute $salutationRoute;
  68.         $this->addressRoute $addressRoute;
  69.         $this->cartService $cartService;
  70.         $this->paymentMethodRepository $paymentMethodRepository;
  71.         $this->shippingMethodRepository $shippingMethodRepository;
  72.     }
  73.     public static function getSubscribedEvents(): array
  74.     {
  75.         return [
  76.             CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmPageLoaded',
  77.             CheckoutFinishPageLoadedEvent::class => 'onCheckoutFinishPageLoaded',
  78.             SalesChannelContextSwitchEvent::class => 'onSalesChannelContextSwitched',
  79.             GuestCustomerRegisterEvent::class => 'onGuestCustomerRegisterEvent',
  80.             BeforeLineItemRemovedEvent::class => 'onLineItemRemovedEvent',
  81.         ];
  82.     }
  83.     public function onLineItemRemovedEvent(BeforeLineItemRemovedEvent $event): void
  84.     {
  85.         $_SESSION['REMOVED_LINEITEM'] = $event->getLineItem();
  86.     }
  87.     public function onGuestCustomerRegisterEvent(GuestCustomerRegisterEvent $event): void
  88.     {
  89.         // Show Shipping after registration in checkout instead of the address accordion
  90.         $_SESSION['step'] = '#customerShipping';
  91.         $_SESSION['useDefaultPayment'] = true;
  92.     }
  93.     public function onSalesChannelContextSwitched(SalesChannelContextSwitchEvent $event): void
  94.     {
  95.         $shippingMethodId $event->getRequestDataBag()->get(SalesChannelContextService::SHIPPING_METHOD_ID);
  96.         if($shippingMethodId) {
  97.             /** @var ShippingMethodEntity $shippingMethod */
  98.             $shippingMethod $this->shippingMethodRepository->search(new Criteria([$shippingMethodId]), $event->getContext())->first();
  99.             if($shippingMethod !== null) {
  100.                 $_SESSION['ADD_SHIPPING_INFO'] = [
  101.                     'shippingMethod' => $shippingMethod->getName()
  102.                 ];
  103.             }
  104.         }
  105.         $paymentMethodId $event->getRequestDataBag()->get(SalesChannelContextService::PAYMENT_METHOD_ID);
  106.         if($paymentMethodId) {
  107.             /** @var PaymentMethodEntity $paymentMethod */
  108.             $paymentMethod $this->paymentMethodRepository->search(new Criteria([$paymentMethodId]), $event->getContext())->first();
  109.             if($paymentMethod !== null) {
  110.                 $_SESSION['ADD_PAYMENT_INFO'] = [
  111.                     'paymentMethod' => $paymentMethod->getName()
  112.                 ];
  113.             }
  114.         }
  115.         // Show Shipping after shipping or payment changed
  116.         if($event->getRequestDataBag()->get('paymentMethodId') || $event->getRequestDataBag()->get('shippingMethodId')) {
  117.             $_SESSION['step'] = '#customerShipping';
  118.         }
  119.     }
  120.     public function onCheckoutFinishPageLoaded(CheckoutFinishPageLoadedEvent $event): void
  121.     {
  122.         $form $this->loadForm($event->getSalesChannelContext());
  123.         $sessionData $this->session->get('return');
  124.         if($form && $sessionData) {
  125.             $this->eventDispatcher->dispatch(new CustomFormEvent($event->getSalesChannelContext(), $form$sessionData), CustomFormEvent::EVENT_NAME);
  126.         }
  127.         $event->getPage()->addArrayExtension('emailHash', [hash("sha256"$event->getSalesChannelContext()->getCustomer()->getEmail())]);
  128.     }
  129.     public function onCheckoutConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void
  130.     {
  131.         $form $this->loadForm($event->getSalesChannelContext());
  132.         if($form) {
  133.             $this->session->set('returnMessage'$form->getSuccessMessage());
  134.             $event->getPage()->addExtension('swagCmsExtensionsForm'$form);
  135.         }
  136.         if(array_key_exists('step'$_SESSION) && $_SESSION['step'] && $event->getSalesChannelContext()->getCustomer()) {
  137.             // Open payment/shipping accordion if one of them changed
  138.             $event->getPage()->addArrayExtension('step', [$_SESSION['step']]);
  139.             unset($_SESSION['step']);
  140.         }else {
  141.             // Load first step as default value
  142.             $event->getPage()->addArrayExtension('step', ['#customerData']);
  143.         }
  144.         //dd($event->getPage(), $event->getSalesChannelContext());
  145.         // Keep sorting, do not use active as first item
  146.         $paymentMethods $event->getPage()->getPaymentMethods();
  147.         $paymentMethods->sort(fn($a$b) => $a->getPosition() > $b->getPosition());
  148.         $event->getPage()->setPaymentMethods($paymentMethods);
  149.         $shippingMethods $event->getPage()->getShippingMethods();
  150.         $shippingMethods->sort(fn($a$b) => $a->getId() > $b->getId());
  151.         $event->getPage()->setShippingMethods($shippingMethods);
  152.         $salutations $this->loadSalutations($event->getSalesChannelContext());
  153.         $event->getPage()->addExtension('salutations'$salutations);
  154.         $criteria = (new Criteria())->addFilter(new EqualsFilter('active'true))->addAssociation('states');
  155.         $countries $this->countryRoute->load(new Request(), $criteria$event->getSalesChannelContext())->getCountries();
  156.         $countries->sortCountryAndStates();
  157.         $event->getPage()->addExtension('countries'$countries);
  158.         // Append data to billing/shipping forms
  159.         if($customer $event->getSalesChannelContext()->getCustomer()) {
  160.             $shippingAddress json_decode(json_encode($customer->getActiveShippingAddress()), true);
  161.             $shippingAddress['accountType'] = 'private';
  162.             $bag = new RequestDataBag();
  163.             $bag->set('salutationId'$customer->getSalutationId());
  164.             $bag->set('firstName'$customer->getFirstName());
  165.             $bag->set('lastName'$customer->getLastName());
  166.             $bag->set('email'$customer->getEmail());
  167.             $bag->set('billingAddress'$customer->getActiveBillingAddress());
  168.             $bag->set('shippingAddress'$shippingAddress);
  169.             $bag->set('guest'true);
  170.             $event->getPage()->addExtension('data', new ArrayStruct([$bag]));
  171.             $criteria = (new Criteria())->addSorting(new FieldSorting('firstName'FieldSorting::ASCENDING));
  172.             $event->getPage()->addExtension('addresses'$this->addressRoute->load($criteria$event->getSalesChannelContext(), $customer)->getAddressCollection());
  173.         }
  174.     }
  175.     private function loadSalutations(SalesChannelContext $salesChannelContext): SalutationCollection
  176.     {
  177.         return $this->salutationRoute->load(new Request(), $salesChannelContext, new Criteria())->getSalutations();
  178.     }
  179.     private function loadForm(SalesChannelContext $context): ?FormEntity
  180.     {
  181.         $criteria = new Criteria();
  182.         $criteria->addFilter(new EqualsFilter('technicalName''Geräterückgabe'));
  183.         $criteria->addAssociation('groups.fields');
  184.         $criteria->addAssociation('mailTemplate');
  185.         $criteria->getAssociation('groups')
  186.             ->addSorting(new FieldSorting('position'))
  187.             ->getAssociation('fields')
  188.             ->addSorting(new FieldSorting('position'));
  189.         // Dependency can be empty, if plugin is not installed
  190.         if(!$this->formRepository) {
  191.             return null;
  192.         }
  193.         /** @var FormEntity|null $form */
  194.         $form $this->formRepository->search($criteria$context->getContext())->getEntities()->first();
  195.         if(!$form) {
  196.             return null;
  197.         }
  198.         /** @var FormGroupEntity $group */
  199.         foreach($form->getGroups() as $group) {
  200.             /** @var FormGroupFieldEntity $field */
  201.             foreach($group->getFields() as $field) {
  202.                 if($field->getType() === 'select' && array_key_exists('entity'$field->getConfig()) && $field->getConfig()['entity'] === 'salutation') {
  203.                     $result $this->loadSalutations($context);
  204.                     $options = [];
  205.                     foreach ($result as $entity) {
  206.                         $options[$entity->getId()] = $entity->getTranslation('displayName');
  207.                     }
  208.                     $translated $field->getTranslated();
  209.                     $translated['config']['options'] = $options;
  210.                     $field->setTranslated($translated);
  211.                 }
  212.             }
  213.         }
  214.         return $form;
  215.     }
  216. }