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

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