custom/plugins/AtlProductConfigurator/src/Subscriber/LineItemAddedSubscriber.php line 62

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Atl\ProductConfigurator\Subscriber;
  3. use Atl\ProductConfigurator\Core\Content\ProductConfigurator\ProductConfiguratorEntity;
  4. use Atl\ProductConfigurator\Core\Content\ProductConfigurator\SalesChannel\Price\PriceService;
  5. use Atl\ProductConfigurator\Migration\Migration1628124328ProductExtension;
  6. use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
  7. use Shopware\Core\Content\Product\ProductEntity;
  8. use Shopware\Core\Content\Product\SalesChannel\Price\ProductPriceCalculator;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\Uuid\Uuid;
  12. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  13. use Symfony\Component\HttpFoundation\RequestStack;
  14. class LineItemAddedSubscriber implements EventSubscriberInterface
  15. {
  16.     /**
  17.      * @var EntityRepositoryInterface
  18.      */
  19.     private $productRepository;
  20.     /**
  21.      * @var RequestStack
  22.      */
  23.     private $requestStack;
  24.     /**
  25.      * @var PriceService
  26.      */
  27.     private $priceService;
  28.     /**
  29.      * @var ProductPriceCalculator
  30.      */
  31.     private $productPriceCalculator;
  32.     public function __construct(
  33.         EntityRepositoryInterface $productRepository,
  34.         RequestStack $requestStack,
  35.         PriceService $priceService,
  36.         ProductPriceCalculator $productPriceCalculator
  37.     )
  38.     {
  39.         $this->productRepository $productRepository;
  40.         $this->requestStack $requestStack;
  41.         $this->priceService $priceService;
  42.         $this->productPriceCalculator $productPriceCalculator;
  43.     }
  44.     public static function getSubscribedEvents(): array
  45.     {
  46.         return [
  47.             BeforeLineItemAddedEvent::class => "onLineItemAdded"
  48.         ];
  49.     }
  50.     /**
  51.      * @param BeforeLineItemAddedEvent $event
  52.      */
  53.     public function onLineItemAdded(BeforeLineItemAddedEvent $event): void
  54.     {
  55.         $lineItems $this->requestStack->getMainRequest()->request->get("lineItems");
  56.         // Prevent checkout login error
  57.         if (empty($lineItems)) {
  58.             return;
  59.         }
  60.         foreach ($lineItems as $lineItem) {
  61.             if (empty($lineItem["atlProductConfigurator"])) {
  62.                 continue;
  63.             }
  64.             if (!$lineItem['productConfiguration']) {
  65.                 // TODO: Fix stackable of non-configured products
  66.                 $event->getLineItem()->setId(Uuid::randomHex());
  67.                 continue;
  68.             }
  69.             // Filter empty inputs
  70.             $inputFields array_filter($lineItem["atlProductConfigurator"]);
  71.             $productConfigurator $this->loadProductConfigurator($event);
  72.             // Build payload
  73.             $payload = [];
  74.             $position 0;
  75.             foreach ($inputFields as $key => $input) {
  76.                 if ($key === 'dropdown') {
  77.                     $label $this->getLabelForDropdown($productConfigurator);
  78.                 } else {
  79.                     $label $this->getLabelForTextField($key$productConfigurator);
  80.                 }
  81.                 $payload[$key] = [
  82.                     "label" => $label,
  83.                     "value" => $input,
  84.                     "position" => $position
  85.                 ];
  86.                 $position += 1;
  87.             }
  88.             // Create new line item to avoid stacking when added
  89.             $event->getLineItem()->setId(Uuid::randomHex());
  90.             $event->getLineItem()->setPayloadValue('atlProductConfigurator'$payload);
  91.             if (empty($productConfigurator->getCalculatedPrice())) {
  92.                 return;
  93.             }
  94.             // Set price
  95.             $event->getLineItem()->setPayloadValue('atlProductConfiguratorPrice'$productConfigurator->getCalculatedPrice()->getUnitPrice());
  96.         }
  97.     }
  98.     /**
  99.      * @param BeforeLineItemAddedEvent $event
  100.      * @return ProductConfiguratorEntity
  101.      */
  102.     private function loadProductConfigurator(BeforeLineItemAddedEvent $event): ProductConfiguratorEntity
  103.     {
  104.         $productId $event->getLineItem()->getId();
  105.         $criteria = new Criteria([$productId]);
  106.         /** @var ProductEntity $field */
  107.         $product $this->productRepository->search($criteria$event->getContext())->first();
  108.         $this->productPriceCalculator->calculate([$product], $event->getSalesChannelContext());
  109.         $event->getLineItem()->setPayloadValue('atlProductConfiguratorProductPrice'$product->calculatedPrice->getUnitPrice());
  110.         $productConfigurator $product->getExtension(Migration1628124328ProductExtension::PRODUCT_EXTENSION);
  111.         $this->priceService->calculatePrice($productConfigurator$event->getSalesChannelContext());
  112.         return $productConfigurator;
  113.     }
  114.     /**
  115.      * @param ProductConfiguratorEntity $productConfigurator
  116.      * @return string
  117.      */
  118.     public function getLabelForDropdown(ProductConfiguratorEntity $productConfigurator): string
  119.     {
  120.         $dropdownLabel $productConfigurator->getDropdownLabel();
  121.         if (empty($dropdownLabel)) {
  122.             return '';
  123.         }
  124.         return $dropdownLabel;
  125.     }
  126.     /**
  127.      * @param string $id
  128.      * @param ProductConfiguratorEntity $productConfigurator
  129.      * @return string
  130.      */
  131.     public function getLabelForTextField(string $idProductConfiguratorEntity $productConfigurator): string
  132.     {
  133.         $field $productConfigurator->getAtlProductConfiguratorFields()->getElements()[$id];
  134.         return $field->getTranslated()['label'];
  135.     }
  136. }