custom/plugins/ZeobvBundleProducts/src/Core/Subscriber/ProductSubscriber.php line 54

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Zeobv\BundleProducts\Core\Subscriber;
  4. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5. use Shopware\Core\Framework\Struct\ArrayStruct;
  6. use Shopware\Core\Content\Product\ProductEntity;
  7. use Shopware\Core\Content\Product\ProductEvents;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
  9. use Shopware\Core\Content\Product\Aggregate\ProductPrice\ProductPriceCollection;
  10. use Shopware\Core\Content\Product\DataAbstractionLayer\CheapestPrice\CheapestPriceContainer;
  11. use Zeobv\BundleProducts\Factory\ProductBundleFactory;
  12. use Zeobv\BundleProducts\Struct\BundleProduct\BundlePrice;
  13. use Zeobv\BundleProducts\Service\ConfigService;
  14. use Zeobv\BundleProducts\Repository\BundleProductRepository;
  15. use Zeobv\BundleProducts\Struct\BundleProduct\ProductBundle;
  16. class ProductSubscriber implements EventSubscriberInterface
  17. {
  18.     protected BundleProductRepository $bundleProductRepository;
  19.     protected ProductBundleFactory $productBundleFactory;
  20.     protected ConfigService $configService;
  21.     public function __construct(
  22.         BundleProductRepository $bundleProductRepository,
  23.         ProductBundleFactory $productBundleFactory,
  24.         ConfigService $configService
  25.     ) {
  26.         $this->bundleProductRepository $bundleProductRepository;
  27.         $this->productBundleFactory $productBundleFactory;
  28.         $this->configService $configService;
  29.     }
  30.     /**
  31.      * @return array
  32.      */
  33.     public static function getSubscribedEvents(): array
  34.     {
  35.         return [
  36.             ProductEvents::PRODUCT_LOADED_EVENT => [
  37.                 ['onProductLoaded', -1]
  38.             ],
  39.         ];
  40.     }
  41.     /**
  42.      * @param EntityLoadedEvent $event
  43.      *
  44.      * @throws \Doctrine\DBAL\Driver\Exception
  45.      * @throws \Doctrine\DBAL\Exception
  46.      */
  47.     public function onProductLoaded(EntityLoadedEvent $event): void
  48.     {
  49.         // We perform another query to get the bundle products,
  50.         // check for the context so we don't want to arrive in an infinite loop
  51.         if ($event->getContext()->hasExtension('zeobvBundleProductContext')) {
  52.             /** @var ArrayStruct $arrayStruct */
  53.             $arrayStruct $event->getContext()->getExtension('zeobvBundleProductContext');
  54.             $contextIds $arrayStruct->all();
  55.             $oldIds $contextIds['productIds'];
  56.             if (count(array_diff($event->getIds(), $oldIds)) == 0) {
  57.                 $event->getContext()->removeExtension('zeobvBundleProductContext');
  58.                 return;
  59.             }
  60.         }
  61.         # Create an index to be able to quickly reference products later from the ProductCollection using the product ID
  62.         $index array_flip($event->getIds());
  63.         # Get products of bundles grouped by product id, we can call these "Bundles"
  64.         $bundles $this->bundleProductRepository->getBundleProductContents($event->getIds(), $event->getContext());
  65.         if (count($bundles) < 1) {
  66.             return;
  67.         }
  68.         # Loop over the bundles to determine availability of the so-called "bundle product"
  69.         # and create a ProductBundle struct for later use.
  70.         foreach ($bundles as $bundleProductId => $productsInBundle) {
  71.             /** @var ProductEntity $productEntity */
  72.             $productEntity $event->getEntities()[$index[$bundleProductId]] ?? $event->getEntities()[$bundleProductId];
  73.             $productBundle $this->productBundleFactory->create($bundleProductId$productsInBundle);
  74.             if (
  75.                 $productBundle->getBundlePriceMode() === BundlePrice::BUNDLE_PRICE_MODE_SUM
  76.                 && $productBundle->getBundlePrice()
  77.             ) {
  78.                 # Set new price
  79.                 $productEntity->setPrice($productBundle->getBundlePrice()->getPrice());
  80.                 $productEntity->setPrices($productBundle->getAdvancedPrices() ?: new ProductPriceCollection([]));
  81.                 $productEntity->setCheapestPriceContainer(new CheapestPriceContainer([]));
  82.                 # @feature-deprecated  (flag:FEATURE_NEXT_15815) tag:v6.5.0 -
  83.                 # CheapestPrice will only be available for SalesChannelProductEntity
  84.                 if (method_exists($productEntity'setCheapestPrice')) {
  85.                     $productEntity->setCheapestPrice(null);
  86.                 }
  87.             }
  88.             if ($this->configService->overridePurchasePrice()) {
  89.                 $productEntity->setPurchasePrices($productBundle->getBundlePurchasePrice()->getPrice());
  90.             }
  91.             if ($productBundle->getOverrideStockFieldOfBundleProduct()) {
  92.                 $productEntity->setStock($productBundle->getVirtualStock());
  93.             }
  94.             $productEntity->setAvailableStock($productBundle->getVirtualAvailableStock());
  95.             if ($this->configService->getOverrideMaxPurchase()) {
  96.                 $productEntity->setMaxPurchase($productBundle->getMaxPurchase());
  97.             }
  98.             $productEntity->setIsCloseout($productBundle->isBackordersDisabled());
  99.             if ($productBundle->getDeliveryTime() !== null) {
  100.                 $productEntity->setDeliveryTimeId($productBundle->getDeliveryTime()->getId());
  101.                 $productEntity->setDeliveryTime($productBundle->getDeliveryTime());
  102.             }
  103.             if (!$this->configService->getOverrideBundleWeight() &&  $productBundle->getWeight() > 0) {
  104.                 $productEntity->setWeight($productBundle->getWeight());
  105.             } elseif ($this->configService->getOverrideBundleWeight()) {
  106.                 $productEntity->setWeight($this->configService->getBundleWeightOverride());
  107.             }
  108.             if ($productBundle->isBackordersDisabled()) {
  109.                 $productEntity->setAvailable($productBundle->isInStock());
  110.             }
  111.             $productEntity->addExtension(ProductBundle::EXTENSION_NAME$productBundle);
  112.         }
  113.     }
  114. }