custom/plugins/TmmsProductCustomerInputs/src/Storefront/Subscriber/FrontendSubscriber.php line 162

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