custom/plugins/CioProductCustomerInputs/src/Storefront/Subscriber/FrontendSubscriber.php line 101

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace CioProductCustomerInputs\Storefront\Subscriber;
  4. use CioProductCustomerInputs\CioProductCustomerInputs;
  5. use CioProductCustomerInputs\Service\SessionService;
  6. use Shopware\Core\Checkout\Cart\Event\AfterLineItemAddedEvent;
  7. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  8. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  9. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  10. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  11. use Shopware\Core\Content\Product\ProductEntity;
  12. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  13. use Shopware\Core\Framework\Context;
  14. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  15. use Shopware\Core\System\SystemConfig\SystemConfigService;
  16. use Shopware\Storefront\Page\Account\Order\AccountOrderPageLoadedEvent;
  17. use Shopware\Storefront\Page\Account\Overview\AccountOverviewPageLoadedEvent;
  18. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
  19. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  20. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  21. use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
  22. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  23. use Swag\CmsExtensions\Storefront\Pagelet\Quickview\QuickviewPageletLoadedEvent;
  24. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  25. use Symfony\Component\HttpFoundation\RedirectResponse;
  26. use Symfony\Contracts\Translation\TranslatorInterface;
  27. class FrontendSubscriber implements EventSubscriberInterface
  28. {
  29.     /**
  30.      * @var TranslatorInterface
  31.      */
  32.     private TranslatorInterface $translator;
  33.     /**
  34.      * @var SystemConfigService
  35.      */
  36.     private SystemConfigService $systemConfigService;
  37.     /**
  38.      * @var EntityRepositoryInterface
  39.      */
  40.     private EntityRepositoryInterface $orderLineItemRepository;
  41.     /**
  42.      * @var SessionService
  43.      */
  44.     private SessionService $sessionService;
  45.     private CartService $cartService;
  46.     public function __construct(
  47.         TranslatorInterface       $translator,
  48.         SystemConfigService       $systemConfigService,
  49.         EntityRepositoryInterface $orderLineItemRepository,
  50.         SessionService            $sessionService,
  51.         CartService               $cartService
  52.     )
  53.     {
  54.         $this->translator $translator;
  55.         $this->systemConfigService $systemConfigService;
  56.         $this->orderLineItemRepository $orderLineItemRepository;
  57.         $this->sessionService $sessionService;
  58.         $this->cartService $cartService;
  59.     }
  60.     public static function getSubscribedEvents(): array
  61.     {
  62.         if (class_exists('\\Swag\\CmsExtensions\\Storefront\\Pagelet\\Quickview\\QuickviewPageletLoadedEvent')) {
  63.             return [
  64.                 ProductPageLoadedEvent::class => 'onProductPageLoaded',
  65.                 CheckoutCartPageLoadedEvent::class => 'onCheckoutCartPageLoaded',
  66.                 CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmPageLoaded',
  67.                 CheckoutFinishPageLoadedEvent::class => 'onCheckoutFinishPageLoaded',
  68.                 CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlaced',
  69.                 AccountOrderPageLoadedEvent::class => 'onAccountOrderPageLoaded',
  70.                 AccountOverviewPageLoadedEvent::class => 'onAccountOverviewPageLoaded',
  71.                 QuickviewPageletLoadedEvent::class => 'onQuickviewPageletLoaded',
  72.                 OffcanvasCartPageLoadedEvent::class => 'onOffcanvasCartPageLoadedEvent',
  73.                 AfterLineItemAddedEvent::class => 'onLineItemAdded'
  74.             ];
  75.         } else {
  76.             return [
  77.                 ProductPageLoadedEvent::class => 'onProductPageLoaded',
  78.                 CheckoutCartPageLoadedEvent::class => 'onCheckoutCartPageLoaded',
  79.                 CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmPageLoaded',
  80.                 CheckoutFinishPageLoadedEvent::class => 'onCheckoutFinishPageLoaded',
  81.                 CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlaced',
  82.                 AccountOrderPageLoadedEvent::class => 'onAccountOrderPageLoaded',
  83.                 AccountOverviewPageLoadedEvent::class => 'onAccountOverviewPageLoaded',
  84.                 OffcanvasCartPageLoadedEvent::class => 'onOffcanvasCartPageLoadedEvent',
  85.                 AfterLineItemAddedEvent::class => 'onLineItemAdded'
  86.             ];
  87.         }
  88.     }
  89.     /**
  90.      * provide the customer input on the product detail page
  91.      */
  92.     public function onProductPageLoaded(ProductPageLoadedEvent $event): SalesChannelProductEntity
  93.     {
  94.         $customerInputShowOnProductDetailPage $this->systemConfigService->get('CioProductCustomerInputs.config.customerInputShowOnProductDetailPage');
  95.         $product $event->getPage()->getProduct();
  96.         $lineItemId $event->getRequest()->get('lineItemId');
  97.         if (!is_null($lineItemId)) {
  98.             if (!$this->cartService->getCart($event->getSalesChannelContext()->getToken(), $event->getSalesChannelContext())->has($lineItemId)) {
  99.                 $request $event->getRequest();
  100.                 $response = new RedirectResponse($request->getRequestUri());
  101.                 $response->send();
  102.             }
  103.         }
  104.         if ($customerInputShowOnProductDetailPage == 'yes') {
  105.             if ($product->getCustomFields() && is_array($product->getCustomFields()) && isset($product->getCustomFields()['cio_customer_input_count_rows'])) {
  106.                 for ($row 1$row <= $product->getCustomFields()['cio_customer_input_count_rows']; ++$row) {
  107.                     for ($i 1$i <= CioProductCustomerInputs::CUSTOMER_INPUT_COUNT; ++$i) {
  108.                         $productExtensionData['value'] = $this->sessionService->getCustomerInputFromSession($product->getProductNumber(), 'value'$row$i$lineItemId);
  109.                         $productExtensionData['checkboxValue'] = $this->sessionService->getCustomerInputFromSession($product->getProductNumber(), 'checkbox_value'$row$i$lineItemId);
  110.                         $productExtension $this->sessionService->createArrayEntity($productExtensionData);
  111.                         $product->addExtension('cioCustomerInput' $row $i$productExtension);
  112.                     }
  113.                 }
  114.             }
  115.         }
  116.         $cioCustomerInputCount['value'] = CioProductCustomerInputs::CUSTOMER_INPUT_COUNT;
  117.         $cioCustomerInputCountValue $this->sessionService->createArrayEntity($cioCustomerInputCount);
  118.         $product->addExtension('cioCustomerInputCountValue'$cioCustomerInputCountValue);
  119.         return $product;
  120.     }
  121.     /**
  122.      * provide the customer input on the checkout cart page
  123.      */
  124.     public function onCheckoutCartPageLoaded(CheckoutCartPageLoadedEvent $event): array
  125.     {
  126.         return $this->getLineItemsCustomerInput($event->getPage()->getCart()->getLineItems()->getElements());
  127.     }
  128.     /**
  129.      * provide the customer input on the off-canvas cart page
  130.      */
  131.     public function onOffcanvasCartPageLoadedEvent(OffcanvasCartPageLoadedEvent $event): array
  132.     {
  133.         return $this->getLineItemsCustomerInput($event->getPage()->getCart()->getLineItems()->getElements());
  134.     }
  135.     /**
  136.      * provide the customer input on the checkout confirm page
  137.      */
  138.     public function onCheckoutConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): array
  139.     {
  140.         return $this->getLineItemsCustomerInput($event->getPage()->getCart()->getLineItems()->getElements());
  141.     }
  142.     /**
  143.      * save the customer inputs in the order line item custom fields after a successful order
  144.      */
  145.     public function onCheckoutFinishPageLoaded(CheckoutFinishPageLoadedEvent $event): void
  146.     {
  147.         $this->getLineItemsCustomerInput($event->getPage()->getOrder()->getLineItems()->getElements());
  148.         $event->getPage()->assign([
  149.             'cioCustomerInputCountValue' => CioProductCustomerInputs::CUSTOMER_INPUT_COUNT,
  150.         ]);
  151.     }
  152.     /**
  153.      * save the customer inputs in the order line item custom fields when order is placed
  154.      */
  155.     public function onCheckoutOrderPlaced(CheckoutOrderPlacedEvent $event): void
  156.     {
  157.         $lineItems $event->getOrder()->getLineItems();
  158.         $this->saveCustomerInputsInLineItemCustomFields($event$lineItemsfalse);
  159.     }
  160.     /**
  161.      * assign the customer input count value to the account order page
  162.      */
  163.     public function onAccountOrderPageLoaded(AccountOrderPageLoadedEvent $event): void
  164.     {
  165.         $event->getPage()->assign([
  166.             'cioCustomerInputCountValue' => CioProductCustomerInputs::CUSTOMER_INPUT_COUNT,
  167.         ]);
  168.     }
  169.     /**
  170.      * assign the customer input count value to the account overview page
  171.      */
  172.     public function onAccountOverviewPageLoaded(AccountOverviewPageLoadedEvent $event): void
  173.     {
  174.         $event->getPage()->assign([
  175.             'cioCustomerInputCountValue' => CioProductCustomerInputs::CUSTOMER_INPUT_COUNT,
  176.         ]);
  177.     }
  178.     /**
  179.      * provide the customer input on the quickview
  180.      * @param QuickviewPageletLoadedEvent
  181.      * @return ProductEntity
  182.      */
  183.     public function onQuickviewPageletLoaded($event): ProductEntity
  184.     {
  185.         $customerInputShowOnProductDetailPage $this->systemConfigService->get('CioProductCustomerInputs.config.customerInputShowOnProductDetailPage');
  186.         $product $event->getPagelet()->getProduct();
  187.         if ($customerInputShowOnProductDetailPage == 'yes') {
  188.             for ($row 1$row <= $product->getCustomFields()['cio_customer_input_count_rows']; ++$row) {
  189.                 for ($i 1$i <= CioProductCustomerInputs::CUSTOMER_INPUT_COUNT; ++$i) {
  190.                     $productExtensionData['value'] = $this->sessionService->getCustomerInputFromSession($product->getProductNumber(), 'value'$row$i);
  191.                     $productExtensionData['checkboxValue'] = $this->sessionService->getCustomerInputFromSession($product->getProductNumber(), 'checkbox_value'$row$i);
  192.                     $productExtension $this->sessionService->createArrayEntity($productExtensionData);
  193.                     $product->addExtension('cioCustomerInput' $row $i$productExtension);
  194.                 }
  195.             }
  196.         }
  197.         $cioCustomerInputCount['value'] = CioProductCustomerInputs::CUSTOMER_INPUT_COUNT;
  198.         $cioCustomerInputCountValue $this->sessionService->createArrayEntity($cioCustomerInputCount);
  199.         $product->addExtension('cioCustomerInputCountValue'$cioCustomerInputCountValue);
  200.         return $product;
  201.     }
  202.     public function onLineItemAdded(AfterLineItemAddedEvent $event)
  203.     {
  204.         foreach ($event->getLineItems() as $lineItem) {
  205.             $this->sessionService->cloneSessionToLineItemSession($lineItem);
  206.         }
  207.     }
  208.     /**
  209.      * save the customer inputs in the order line item custom fields
  210.      */
  211.     protected function saveCustomerInputsInLineItemCustomFields($event$lineItems$isCheckoutFinishPage): void
  212.     {
  213.         $customerInputTransferUnselectedCheckboxFieldsAsValue $this->systemConfigService->get('CioProductCustomerInputs.config.customerInputTransferUnselectedCheckboxFieldsAsValue');
  214.         foreach ($lineItems as $item) {
  215.             /** @var OrderLineItemEntity $item */
  216.             if ($item->getType() !== LineItem::PROMOTION_LINE_ITEM_TYPE) {
  217.                 $productNumber $item->getPayload()['productNumber'];
  218.                 $cioCustomerInputValueArray = [];
  219.                 $cioCustomerInputHasValue 0;
  220.                 if (isset($item->getPayload()['customFields']['cio_customer_input_count_rows'])) {
  221.                     for ($row 1$row <= $item->getPayload()['customFields']['cio_customer_input_count_rows']; ++$row) {
  222.                         for ($i 1$i <= CioProductCustomerInputs::CUSTOMER_INPUT_COUNT; ++$i) {
  223.                             $cioCustomerInputValue $this->sessionService->getCustomerInputFromSession($productNumber'value'$row$i$item->getIdentifier());
  224.                             $cioCustomerInputCheckboxValue $this->sessionService->getCustomerInputFromSession($productNumber'checkbox_value'$row$i$item->getIdentifier());
  225.                             $cioCustomerInputLabel $this->sessionService->getCustomerInputFromSession($productNumber'label'$row$i$item->getIdentifier());
  226.                             $cioCustomerInputPlaceholder $this->sessionService->getCustomerInputFromSession($productNumber'placeholder'$row$i$item->getIdentifier());
  227.                             $cioCustomerInputFieldType $this->sessionService->getCustomerInputFromSession($productNumber'fieldtype'$row$i$item->getIdentifier());
  228.                             if ($cioCustomerInputValue || (($customerInputTransferUnselectedCheckboxFieldsAsValue) && ($cioCustomerInputFieldType == 'boolean') && ($cioCustomerInputValue == 0)) || ($cioCustomerInputFieldType == 'input' && $cioCustomerInputValue == '0')) {
  229.                                 $cioCustomerInputValueArray[$row][$i]['value'] = ($cioCustomerInputFieldType == 'boolean' ? ($cioCustomerInputValue == $this->translator->trans('cio.customerInput.selectedValue') : $this->translator->trans('cio.customerInput.unselectedValue')) : $cioCustomerInputValue);
  230.                                 $cioCustomerInputValueArray[$row][$i]['checkbox_value'] = $cioCustomerInputCheckboxValue;
  231.                                 $cioCustomerInputValueArray[$row][$i]['label'] = $cioCustomerInputLabel;
  232.                                 $cioCustomerInputValueArray[$row][$i]['placeholder'] = $cioCustomerInputPlaceholder;
  233.                                 $cioCustomerInputValueArray[$row][$i]['fieldtype'] = $cioCustomerInputFieldType;
  234.                                 $cioCustomerInputHasValue $cioCustomerInputHasValue 1;
  235.                             } elseif ($customerInputTransferUnselectedCheckboxFieldsAsValue) {
  236.                                 if ($item->getCustomFields() and (!isset($item->getCustomFields()['cio_customer_input_' $i '_value']))) {
  237.                                     $productCustomFields $item->getPayload()['customFields'];
  238.                                     if (isset($productCustomFields['cio_customer_input_' $i '_active'])) {
  239.                                         if ($productCustomFields['cio_customer_input_' $i '_active'] && $productCustomFields['cio_customer_input_' $i '_fieldtype'] == 'boolean') {
  240.                                             $cioCustomerInputValue $this->sessionService->getCustomerInputFromSession($productNumber'value'$row$i$item->getId());
  241.                                             if ($cioCustomerInputValue == '') {
  242.                                                 $cioCustomerInputValue $this->translator->trans('cio.customerInput.unselectedValue');
  243.                                                 $cioCustomerInputLabel = (isset($productCustomFields['cio_customer_input_' $i '_title']) ? ($productCustomFields['cio_customer_input_' $i '_title'] !== '' $productCustomFields['cio_customer_input_' $i '_title'] : $this->translator->trans('cio.customerInput.titleLabel')) : $this->translator->trans('cio.customerInput.titleLabel'));
  244.                                                 $cioCustomerInputPlaceholder = (isset($productCustomFields['cio_customer_input_' $i '_placeholder']) ? ($productCustomFields['cio_customer_input_' $i '_placeholder'] !== '' $productCustomFields['cio_customer_input_' $i '_placeholder'] : $this->translator->trans('cio.customerInput.placeholderLabel')) : $this->translator->trans('cio.customerInput.placeholderLabel'));
  245.                                                 $cioCustomerInputFieldType $productCustomFields['cio_customer_input_' $i '_fieldtype'];
  246.                                                 $cioCustomerInputValueArray[$row][$i]['value'] = $cioCustomerInputValue;
  247.                                                 $cioCustomerInputValueArray[$row][$i]['label'] = $cioCustomerInputLabel;
  248.                                                 $cioCustomerInputValueArray[$row][$i]['placeholder'] = $cioCustomerInputPlaceholder;
  249.                                                 $cioCustomerInputValueArray[$row][$i]['fieldtype'] = $cioCustomerInputFieldType;
  250.                                                 $cioCustomerInputHasValue $cioCustomerInputHasValue 1;
  251.                                             }
  252.                                         }
  253.                                     }
  254.                                 }
  255.                             }
  256.                         }
  257.                     }
  258.                 }
  259.                 $cioCustomerInputValueCustomFieldArray = [];
  260.                 $cioCustomerInputValueTypeArray = array('value''checkbox_value''label''placeholder''fieldtype');
  261.                 if (isset($item->getPayload()['customFields']['cio_customer_input_count_rows'])) {
  262.                     for ($row 1$row <= $item->getPayload()['customFields']['cio_customer_input_count_rows']; ++$row) {
  263.                         for ($i 1$i <= CioProductCustomerInputs::CUSTOMER_INPUT_COUNT; ++$i) {
  264.                             foreach ($cioCustomerInputValueTypeArray as $ta) {
  265.                                 if (isset($cioCustomerInputValueArray[$row][$i][$ta])) {
  266.                                     $cioCustomerInputValueCustomFieldArray['cio_customer_input_' $row '_' $i '_' $ta] = $cioCustomerInputValueArray[$row][$i][$ta];
  267.                                 }
  268.                             }
  269.                         }
  270.                     }
  271.                 }
  272.                 $item->setCustomFields(
  273.                     $cioCustomerInputValueCustomFieldArray
  274.                 );
  275.                 if ($isCheckoutFinishPage) {
  276.                     for ($row 1$row <= $item->getPayload()['customFields']['cio_customer_input_count_rows']; ++$row) {
  277.                         for ($i 1$i <= CioProductCustomerInputs::CUSTOMER_INPUT_COUNT; ++$i) {
  278.                             $this->sessionService->removeCustomerInputFromSession($productNumber$row$i$item->getId());
  279.                         }
  280.                     }
  281.                 }
  282.                 if ($cioCustomerInputHasValue 0) {
  283.                     $this->orderLineItemRepository->upsert(
  284.                         [
  285.                             [
  286.                                 'id' => $item->getId(),
  287.                                 'customFields' => $item->getCustomFields(),
  288.                             ],
  289.                         ],
  290.                         $event->getContext() ?? Context::createDefaultContext()
  291.                     );
  292.                 }
  293.             }
  294.         }
  295.     }
  296.     /**
  297.      * get the customer input for each line item
  298.      */
  299.     private function getLineItemsCustomerInput($lineItems): array
  300.     {
  301.         foreach ($lineItems as $lineItem) {
  302.             $this->sessionService->addLineItemsCustomerInput($lineItem);
  303.         }
  304.         return $lineItems;
  305.     }
  306. }