vendor/shopware/core/Content/Product/Subscriber/ProductSubscriber.php line 80

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Product\Subscriber;
  3. use Shopware\Core\Content\Product\AbstractIsNewDetector;
  4. use Shopware\Core\Content\Product\AbstractProductMaxPurchaseCalculator;
  5. use Shopware\Core\Content\Product\AbstractProductVariationBuilder;
  6. use Shopware\Core\Content\Product\AbstractPropertyGroupSorter;
  7. use Shopware\Core\Content\Product\AbstractSalesChannelProductBuilder;
  8. use Shopware\Core\Content\Product\DataAbstractionLayer\CheapestPrice\CheapestPriceContainer;
  9. use Shopware\Core\Content\Product\ProductDefinition;
  10. use Shopware\Core\Content\Product\ProductEntity;
  11. use Shopware\Core\Content\Product\ProductEvents;
  12. use Shopware\Core\Content\Product\SalesChannel\Price\AbstractProductPriceCalculator;
  13. use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
  14. use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionCollection;
  15. use Shopware\Core\Framework\Context;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Entity;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Event\PartialEntityLoadedEvent;
  19. use Shopware\Core\Framework\Feature;
  20. use Shopware\Core\Framework\Log\Package;
  21. use Shopware\Core\System\SalesChannel\Entity\PartialSalesChannelEntityLoadedEvent;
  22. use Shopware\Core\System\SalesChannel\Entity\SalesChannelEntityLoadedEvent;
  23. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  24. use Shopware\Core\System\SystemConfig\SystemConfigService;
  25. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  26. /**
  27.  * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  28.  */
  29. #[Package('inventory')]
  30. class ProductSubscriber implements EventSubscriberInterface
  31. {
  32.     private AbstractSalesChannelProductBuilder $salesChannelProductBuilder;
  33.     private AbstractProductVariationBuilder $productVariationBuilder;
  34.     private AbstractProductPriceCalculator $calculator;
  35.     private AbstractPropertyGroupSorter $propertyGroupSorter;
  36.     private AbstractProductMaxPurchaseCalculator $maxPurchaseCalculator;
  37.     private AbstractIsNewDetector $isNewDetector;
  38.     private SystemConfigService $systemConfigService;
  39.     /**
  40.      * @internal
  41.      */
  42.     public function __construct(
  43.         AbstractSalesChannelProductBuilder $salesChannelProductBuilder,
  44.         AbstractProductVariationBuilder $productVariationBuilder,
  45.         AbstractProductPriceCalculator $calculator,
  46.         AbstractPropertyGroupSorter $propertyGroupSorter,
  47.         AbstractProductMaxPurchaseCalculator $maxPurchaseCalculator,
  48.         AbstractIsNewDetector $isNewDetector,
  49.         SystemConfigService $systemConfigService
  50.     ) {
  51.         $this->salesChannelProductBuilder $salesChannelProductBuilder;
  52.         $this->productVariationBuilder $productVariationBuilder;
  53.         $this->calculator $calculator;
  54.         $this->propertyGroupSorter $propertyGroupSorter;
  55.         $this->maxPurchaseCalculator $maxPurchaseCalculator;
  56.         $this->isNewDetector $isNewDetector;
  57.         $this->systemConfigService $systemConfigService;
  58.     }
  59.     public static function getSubscribedEvents(): array
  60.     {
  61.         return [
  62.             ProductEvents::PRODUCT_LOADED_EVENT => 'loaded',
  63.             'product.partial_loaded' => 'partialEntityLoaded',
  64.             'sales_channel.' ProductEvents::PRODUCT_LOADED_EVENT => 'salesChannelLoaded',
  65.             'sales_channel.product.partial_loaded' => 'partialSalesChannelLoaded',
  66.         ];
  67.     }
  68.     public function loaded(EntityLoadedEvent $event): void
  69.     {
  70.         $this->entityLoaded($event->getEntities(), $event->getContext());
  71.     }
  72.     /**
  73.      * @internal
  74.      */
  75.     public function partialEntityLoaded(PartialEntityLoadedEvent $event): void
  76.     {
  77.         $this->entityLoaded($event->getEntities(), $event->getContext());
  78.     }
  79.     public function salesChannelLoaded(SalesChannelEntityLoadedEvent $event): void
  80.     {
  81.         $this->productSalesChannelLoaded($event->getEntities(), $event->getSalesChannelContext());
  82.     }
  83.     /**
  84.      * @internal
  85.      */
  86.     public function partialSalesChannelLoaded(PartialSalesChannelEntityLoadedEvent $event): void
  87.     {
  88.         $this->productSalesChannelLoaded($event->getEntities(), $event->getSalesChannelContext());
  89.     }
  90.     /**
  91.      * @param Entity[] $collection
  92.      */
  93.     private function entityLoaded(array $collectionContext $context): void
  94.     {
  95.         /** @var ProductEntity $product */
  96.         foreach ($collection as $product) {
  97.             // CheapestPrice will only be added to SalesChannelProductEntities in the Future
  98.             if (!Feature::isActive('FEATURE_NEXT_16151')) {
  99.                 $price $product->get('cheapestPrice');
  100.                 if ($price instanceof CheapestPriceContainer) {
  101.                     $resolved $price->resolve($context);
  102.                     $product->assign([
  103.                         'cheapestPrice' => $resolved,
  104.                         'cheapestPriceContainer' => $price,
  105.                     ]);
  106.                 }
  107.             }
  108.             $this->setDefaultLayout($product);
  109.             $this->productVariationBuilder->build($product);
  110.         }
  111.     }
  112.     /**
  113.      * @param Entity[] $elements
  114.      */
  115.     private function productSalesChannelLoaded(array $elementsSalesChannelContext $context): void
  116.     {
  117.         /** @var SalesChannelProductEntity $product */
  118.         foreach ($elements as $product) {
  119.             if (Feature::isActive('FEATURE_NEXT_16151')) {
  120.                 $price $product->get('cheapestPrice');
  121.                 if ($price instanceof CheapestPriceContainer) {
  122.                     $resolved $price->resolve($context->getContext());
  123.                     $product->assign([
  124.                         'cheapestPrice' => $resolved,
  125.                         'cheapestPriceContainer' => $price,
  126.                     ]);
  127.                 }
  128.             }
  129.             if (Feature::isActive('v6.5.0.0')) {
  130.                 $assigns = [];
  131.                 if (($properties $product->get('properties')) !== null && $properties instanceof PropertyGroupOptionCollection) {
  132.                     $assigns['sortedProperties'] = $this->propertyGroupSorter->sort($properties);
  133.                 }
  134.                 $assigns['calculatedMaxPurchase'] = $this->maxPurchaseCalculator->calculate($product$context);
  135.                 $assigns['isNew'] = $this->isNewDetector->isNew($product$context);
  136.                 $product->assign($assigns);
  137.             } else {
  138.                 Feature::callSilentIfInactive('v6.5.0.0', function () use ($product$context): void {
  139.                     $this->salesChannelProductBuilder->build($product$context);
  140.                 });
  141.             }
  142.             $this->setDefaultLayout($product$context->getSalesChannelId());
  143.         }
  144.         $this->calculator->calculate($elements$context);
  145.     }
  146.     /**
  147.      * @param Entity $product - typehint as Entity because it could be a ProductEntity or PartialEntity
  148.      */
  149.     private function setDefaultLayout(Entity $product, ?string $salesChannelId null): void
  150.     {
  151.         if (!Feature::isActive('v6.5.0.0') || !$product->has('cmsPageId')) {
  152.             return;
  153.         }
  154.         if ($product->get('cmsPageId') !== null) {
  155.             return;
  156.         }
  157.         $cmsPageId $this->systemConfigService->get(ProductDefinition::CONFIG_KEY_DEFAULT_CMS_PAGE_PRODUCT$salesChannelId);
  158.         if (!$cmsPageId) {
  159.             return;
  160.         }
  161.         $product->assign(['cmsPageId' => $cmsPageId]);
  162.     }
  163. }