custom/plugins/scha1AdditionalProductBasketFields/src/Storefront/Subscriber/SubscriberInterface.php line 140

Open in your IDE?
  1. <?php
  2.   declare(strict_types=1);
  3.   namespace scha1\scha1AdditionalProductBasketFields\Storefront\Subscriber;
  4.   use Shopware\Core\System\SystemConfig\SystemConfigService;
  5.   use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  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\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
  11.   use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  12.   use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  13.   use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
  14.   use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  15.   use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16.   use Symfony\Component\HttpFoundation\Session\Session;
  17.   use Symfony\Contracts\Translation\TranslatorInterface;
  18.   use scha1\scha1AdditionalProductBasketFields\scha1AdditionalProductBasketFields;
  19.   
  20.   /**
  21.    * 
  22.    */
  23.   class SubscriberInterface implements EventSubscriberInterface {
  24.     /**
  25.      * 
  26.      */
  27.     const PRODUCT_LINE_ITEM_TYPE 'product';
  28.     private $session;
  29.     private $translator;
  30.     private $systemConfigService;
  31.     private $orderLineItemRepository;
  32.     
  33.     /**
  34.      * 
  35.      * @param Session $session
  36.      * @param TranslatorInterface $translator
  37.      * @param SystemConfigService $systemConfigService
  38.      * @param EntityRepositoryInterface $orderLineItemRepository
  39.      */
  40.     public function __constructSession $sessionTranslatorInterface $translator,  SystemConfigService $systemConfigServiceEntityRepositoryInterface $orderLineItemRepository ) {
  41.       $this->session $session;
  42.       $this->translator $translator;
  43.       $this->systemConfigService $systemConfigService;
  44.       $this->orderLineItemRepository $orderLineItemRepository;
  45.     }
  46.     
  47.     /**
  48.      * 
  49.      * @return array
  50.      */
  51.     public static function getSubscribedEvents(): array {
  52.       return [ ProductPageLoadedEvent::class => 'onProductPageLoaded'
  53.        OffcanvasCartPageLoadedEvent::class => 'onOffcanvasCartPageLoaded',
  54.        CheckoutCartPageLoadedEvent::class => 'onCheckoutCartPageLoaded',
  55.        CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmPageLoaded',
  56.        CheckoutFinishPageLoadedEvent::class => 'onCheckoutFinishPageLoaded',
  57.        CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlaced',
  58.       ];
  59.     }
  60.     
  61.     /**
  62.      * 
  63.      * provide on the product detail page
  64.      * @param ProductPageLoadedEvent $event
  65.      * @return SalesChannelProductEntity
  66.      */
  67.     public function onProductPageLoaded(ProductPageLoadedEvent $event): SalesChannelProductEntity {
  68.       $showOnProductDetailPage $this->systemConfigService->get('scha1AdditionalProductBasketFields.config.showOnProductDetailPage');
  69.       $product $event->getPage()->getProduct();
  70.       if ($showOnProductDetailPage == 'yes') {
  71.         for ($i 1$i <= scha1AdditionalProductBasketFields::MAX_FIELD; ++$i) {
  72.           $productExtensionData['value'] = $this->getAdditionalProductBasketFieldFromSession($product->getProductNumber(), 'value'$i);
  73.           $productExtension $this->createArrayEntity($productExtensionData);
  74.           $product->addExtension('additionalproductbasketfields' $i$productExtension);
  75.         }
  76.       }
  77.       $additionalproductbasketfieldsCount['value'] = scha1AdditionalProductBasketFields::MAX_FIELD;
  78.       $additionalproductbasketfieldsCountValue $this->createArrayEntity($additionalproductbasketfieldsCount);
  79.       $product->addExtension('additionalproductbasketfieldsCountValue'$additionalproductbasketfieldsCountValue);
  80.       return $product
  81.     }
  82.     
  83.     /**
  84.      * 
  85.      * provide on the offcanvas cart page
  86.      * @param OffcanvasCartPageLoadedEvent $event
  87.      * @return array
  88.      */
  89.     public function onOffcanvasCartPageLoaded(OffcanvasCartPageLoadedEvent $event): array {
  90.       return $this->getLineItemsAdditionalProductBasketField($event);
  91.     }
  92.     
  93.     /**
  94.      * 
  95.      * provide on the checkout cart page
  96.      * @param CheckoutCartPageLoadedEvent $event
  97.      * @return array
  98.      */
  99.     public function onCheckoutCartPageLoaded(CheckoutCartPageLoadedEvent $event): array {
  100.       return $this->getLineItemsAdditionalProductBasketField($event);
  101.     }
  102.     
  103.     /**
  104.      * 
  105.      * provide on the checkout confirm page
  106.      * @param CheckoutConfirmPageLoadedEvent $event
  107.      * @return array
  108.      */
  109.     public function onCheckoutConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): array {
  110.       return $this->getLineItemsAdditionalProductBasketField($event);
  111.     }
  112.     /**
  113.      * 
  114.      * save in the order line item custom fields after a successful order
  115.      * @param CheckoutFinishPageLoadedEvent $event
  116.      */
  117.     public function onCheckoutFinishPageLoaded(CheckoutFinishPageLoadedEvent $event): void {
  118.       $lineItems $event->getPage()->getOrder()->getLineItems();
  119.       $this->saveAdditionalProductBasketFieldsInLineItemCustomFields($event$lineItemstrue);
  120.       $event->getPage()->assign([ 'additionalproductbasketfieldsCountValue' => scha1AdditionalProductBasketFields::MAX_FIELD ]);
  121.     }
  122.     /**
  123.      * 
  124.      * save in the order line item custom fields when order is placed
  125.      * @param CheckoutOrderPlacedEvent $event
  126.      */
  127.     public function onCheckoutOrderPlaced(CheckoutOrderPlacedEvent $event): void {
  128.       $lineItems $event->getOrder()->getLineItems();
  129.       $this->saveAdditionalProductBasketFieldsInLineItemCustomFields($event$lineItemsfalse);
  130.     }
  131.      
  132.     /**
  133.      * 
  134.      * save in the order line item custom fields
  135.      * @param type $event
  136.      * @param type $lineItems
  137.      * @param type $isCheckoutFinishPage
  138.      */
  139.     protected function saveAdditionalProductBasketFieldsInLineItemCustomFields($event$lineItems$isCheckoutFinishPage): void {
  140.       foreach ($lineItems as $lineItem) {
  141.         if ($lineItem->getType() === self::PRODUCT_LINE_ITEM_TYPE) {
  142.           $this->getProductBasketField($event$lineItem$isCheckoutFinishPage);
  143.         }
  144.       }
  145.     }
  146.     
  147.     
  148.     /**
  149.      * 
  150.      * @param type $event
  151.      * @param type $lineItem
  152.      * @param type $isCheckoutFinishPage
  153.      */
  154.     private function getProductBasketField($event$lineItem$isCheckoutFinishPage) {
  155.       $productNumber $lineItem->getPayload()['productNumber'] ?? null;
  156.       if ($lineItem->getType() === self::PRODUCT_LINE_ITEM_TYPE && $productNumber) {
  157.         $additionalproductbasketfieldsValueArray = [];
  158.         $additionalproductbasketfieldsHasValue 0;
  159.         for ($i 1$i <= scha1AdditionalProductBasketFields::MAX_FIELD; ++$i) {
  160.           $additionalproductbasketfieldsValue $this->getAdditionalProductBasketFieldFromSession($productNumber'value'$i);
  161.           $additionalproductbasketfieldsLabel $this->getAdditionalProductBasketFieldFromSession($productNumber'label'$i);
  162.           $additionalproductbasketfieldsPlaceholder $this->getAdditionalProductBasketFieldFromSession($productNumber'placeholder'$i);
  163.           $additionalproductbasketfieldsFieldType $this->getAdditionalProductBasketFieldFromSession($productNumber'fieldtype'$i);
  164.           if ($additionalproductbasketfieldsValue ) {
  165.             $additionalproductbasketfieldsValueArray[$i]['value'] = ($additionalproductbasketfieldsFieldType == 'boolean' ? ($additionalproductbasketfieldsValue == $this->translator->trans('scha1.additionalproductbasketfields.selectedValue') : $this->translator->trans('scha1.additionalproductbasketfields.unselectedValue')) : $additionalproductbasketfieldsValue);
  166.             $additionalproductbasketfieldsValueArray[$i]['label'] = $additionalproductbasketfieldsLabel;
  167.             $additionalproductbasketfieldsValueArray[$i]['placeholder'] = $additionalproductbasketfieldsPlaceholder;
  168.             $additionalproductbasketfieldsValueArray[$i]['fieldtype'] = $additionalproductbasketfieldsFieldType;
  169.             $additionalproductbasketfieldsHasValue $additionalproductbasketfieldsHasValue 1
  170.           }
  171.         }
  172.         $this->getCustomFields($event$lineItem$isCheckoutFinishPage$productNumber$additionalproductbasketfieldsValueArray$additionalproductbasketfieldsHasValue);
  173.       }
  174.     }
  175.     
  176.     
  177.     /**
  178.      * 
  179.      * @param type $event
  180.      * @param type $lineItem
  181.      * @param type $isCheckoutFinishPage
  182.      * @param type $productNumber
  183.      * @param type $additionalproductbasketfieldsValueArray
  184.      * @param type $additionalproductbasketfieldsHasValue
  185.      */
  186.     private function getCustomFields($event$lineItem$isCheckoutFinishPage$productNumber$additionalproductbasketfieldsValueArray$additionalproductbasketfieldsHasValue) {
  187.       $additionalproductbasketfieldsValueCustomFieldArray = [];
  188.       $additionalproductbasketfieldsValueTypeArray = array('value''label''placeholder''fieldtype');
  189.       for ($i 1$i <= scha1AdditionalProductBasketFields::MAX_FIELD; ++$i) {
  190.         foreach ($additionalproductbasketfieldsValueTypeArray as $basketField) {
  191.           if (isset($additionalproductbasketfieldsValueArray[$i][$basketField])) {
  192.             $additionalproductbasketfieldsValueCustomFieldArray['scha1additionalproductbasketfields' $i '_' $basketField] = $additionalproductbasketfieldsValueArray[$i][$basketField]; 
  193.           }
  194.         }
  195.       }
  196.       $lineItem->setCustomFields($additionalproductbasketfieldsValueCustomFieldArray);
  197.       
  198.       if ($isCheckoutFinishPage) {
  199.         for ($i 1$i <= scha1AdditionalProductBasketFields::MAX_FIELD; ++$i) {
  200.          $this->removeAdditionalProductBasketFieldFromSession($productNumber$i);
  201.         } 
  202.       }
  203.       if ($additionalproductbasketfieldsHasValue 0) {
  204.         $this->orderLineItemRepository->upsert([ [ 'id' => $lineItem->getId(), 'customFields' => $lineItem->getCustomFields(),],], $event->getContext() ?? Context::createDefaultContext());
  205.       }
  206.     }
  207.     
  208.     
  209.     
  210.     /**
  211.      * 
  212.      * get for each line item
  213.      * @param type $event
  214.      * @return array
  215.      */
  216.     private function getLineItemsAdditionalProductBasketField($event): array {
  217.       $lineItems $event->getPage()->getCart()->getLineItems()->getElements();
  218.       foreach ($lineItems as $lineItem) {
  219.         if ($lineItem->getType() === self::PRODUCT_LINE_ITEM_TYPE) {
  220.           $this->getLineItemValue($lineItem);
  221.         }
  222.       }
  223.       return $lineItems;
  224.     }
  225.     
  226.     /**
  227.      * get value in line item
  228.      * @param type $lineItem
  229.      */
  230.     private function getLineItemValue($lineItem) {
  231.       $productNumber $lineItem->getPayloadValue('productNumber') ?? null;
  232.       if ($lineItem->getType() === self::PRODUCT_LINE_ITEM_TYPE && $productNumber) {
  233.         for ($i 1$i <= scha1AdditionalProductBasketFields::MAX_FIELD; ++$i) {
  234.           $productExtensionData['value'] = $this->getAdditionalProductBasketFieldFromSession($productNumber'value'$i);
  235.           $lineItemExtension $this->createArrayEntity($productExtensionData);
  236.           $lineItem->addExtension('lineItemadditionalproductbasketfield' $i$lineItemExtension);  
  237.         }
  238.         $lineItemadditionalproductbasketfieldCount['value'] = scha1AdditionalProductBasketFields::MAX_FIELD;
  239.         $lineItemadditionalproductbasketfieldCountValue $this->createArrayEntity($lineItemadditionalproductbasketfieldCount);
  240.         $lineItem->addExtension('lineItemadditionalproductbasketfieldCountValue'$lineItemadditionalproductbasketfieldCountValue);
  241.       }
  242.     }
  243.     
  244.     
  245.     /**
  246.      * 
  247.      * create an ArrayEntity with the given data
  248.      * @param type $extensionData
  249.      * @return ArrayEntity
  250.      */
  251.     private function createArrayEntity($extensionData): ArrayEntity {
  252.       return new ArrayEntity($extensionData);
  253.     }
  254.     
  255.     
  256.     /**
  257.      * 
  258.      * @param type $productNumber
  259.      * @param type $type
  260.      * @param type $count
  261.      * @return string
  262.      */
  263.     private function getAdditionalProductBasketFieldFromSession($productNumber$type$count): string {
  264.       $sessionAdditionalProductBasketField '';
  265.       $additionalproductbasketfields sprintf('scha1additionalproductbasketfields%d_%s'$count$productNumber);
  266.       if ($this->session->has($additionalproductbasketfields)) {
  267.         if (in_array($type, ['value''label''placeholder''fieldtype'])) {
  268.           $sessionAdditionalProductBasketField $this->session->get($additionalproductbasketfields)['scha1additionalproductbasketfields' $type];
  269.         }
  270.         if ($type == 'value' && $sessionAdditionalProductBasketField == null) {
  271.           $sessionAdditionalProductBasketField '';
  272.         }
  273.       }
  274.       return $sessionAdditionalProductBasketField;
  275.     }
  276.     
  277.     /**
  278.      * 
  279.      * removes from the session based on the product number
  280.      * @param type $productNumber
  281.      * @param type $count
  282.      */
  283.     private function removeAdditionalProductBasketFieldFromSession($productNumber$count): void {
  284.       $this->session->remove('scha1additionalproductbasketfields' $count '_' $productNumber); 
  285.     }
  286.   }