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

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