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

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