custom/plugins/SwagCommercial/src/MultiWarehouse/Subscriber/ProductLoadedSubscriber.php line 39

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Commercial\MultiWarehouse\Subscriber;
  3. use Shopware\Commercial\Licensing\License;
  4. use Shopware\Commercial\MultiWarehouse\Domain\Product\StockLoader;
  5. use Shopware\Core\Content\Product\AbstractProductMaxPurchaseCalculator;
  6. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  7. use Shopware\Core\System\SalesChannel\Entity\SalesChannelEntityLoadedEvent;
  8. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  9. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  10. /**
  11.  * @internal
  12.  *
  13.  * @package inventory
  14.  */
  15. class ProductLoadedSubscriber implements EventSubscriberInterface
  16. {
  17.     private StockLoader $stockLoader;
  18.     private AbstractProductMaxPurchaseCalculator $maxPurchaseCalculator;
  19.     public function __construct(
  20.         StockLoader $stockLoader,
  21.         AbstractProductMaxPurchaseCalculator $maxPurchaseCalculator
  22.     ) {
  23.         $this->stockLoader $stockLoader;
  24.         $this->maxPurchaseCalculator $maxPurchaseCalculator;
  25.     }
  26.     public static function getSubscribedEvents(): array
  27.     {
  28.         return [
  29.             'sales_channel.product.loaded' => 'onProductLoaded',
  30.         ];
  31.     }
  32.     public function onProductLoaded(SalesChannelEntityLoadedEvent $event): void
  33.     {
  34.         if (!License::get('MULTI_INVENTORY-3749997')) {
  35.             return;
  36.         }
  37.         $products $this->getCloseoutProducts($event);
  38.         if (!$products) {
  39.             return;
  40.         }
  41.         $this->load(
  42.             $products,
  43.             $event,
  44.         );
  45.     }
  46.     /**
  47.      * @param SalesChannelProductEntity[] $products
  48.      */
  49.     private function load(array $productsSalesChannelEntityLoadedEvent $event): void
  50.     {
  51.         $ids array_column($products'id');
  52.         $context $event->getSalesChannelContext();
  53.         $warehouseStocks $this->stockLoader->fetchStocks($ids$context);
  54.         if (!$warehouseStocks) {
  55.             return;
  56.         }
  57.         foreach ($warehouseStocks as $productId => $stock) {
  58.             /** @var SalesChannelProductEntity[] $entities */
  59.             $entities $event->getEntities();
  60.             $product $this->getProductById($productId$entities);
  61.             if (!$stock['assigned']) {
  62.                 $this->blockProduct($product);
  63.                 continue;
  64.             }
  65.             $this->updateProduct($product$stock['stock'], $context);
  66.         }
  67.     }
  68.     private function updateProduct(
  69.         SalesChannelProductEntity $product,
  70.         int $stock,
  71.         SalesChannelContext $context
  72.     ): void {
  73.         if ($stock <= 0) {
  74.             $this->blockProduct($product);
  75.             return;
  76.         }
  77.         $product->setStock($stock);
  78.         $product->setAvailableStock($stock);
  79.         $product->setCalculatedMaxPurchase($this->maxPurchaseCalculator->calculate($product$context));
  80.         $available $stock >= (int) $product->getMinPurchase();
  81.         $product->setAvailable($available);
  82.     }
  83.     /**
  84.      * @return SalesChannelProductEntity[]
  85.      */
  86.     private function getCloseoutProducts(SalesChannelEntityLoadedEvent $event): array
  87.     {
  88.         /** @var SalesChannelProductEntity[] $products */
  89.         $products $event->getEntities();
  90.         return \array_filter($products, static fn (SalesChannelProductEntity $product) => $product->getIsCloseout());
  91.     }
  92.     /**
  93.      * @param SalesChannelProductEntity[] $products
  94.      */
  95.     private function getProductById(string $id, array $products): SalesChannelProductEntity
  96.     {
  97.         foreach ($products as $product) {
  98.             if ($product->getId() !== $id) {
  99.                 continue;
  100.             }
  101.             return $product;
  102.         }
  103.         throw new \LogicException('Product with given id not found');
  104.     }
  105.     private function blockProduct(SalesChannelProductEntity $product): void
  106.     {
  107.         $product->setAvailableStock(0);
  108.         $product->setAvailable(false);
  109.         $product->setCalculatedMaxPurchase(0);
  110.     }
  111. }