custom/plugins/System4ShopTheme/src/Subscriber/ListingSubscriber.php line 34

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace System4ShopTheme\Subscriber;
  3. use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
  4. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. use Psr\Log\LoggerInterface;
  7. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  8. use System4ShopTheme\Struct\ColorVariantStruct;
  9. use System4ShopTheme\Struct\ColorVariantCollection;
  10. use Shopware\Core\Content\Product\ProductEntity;
  11. class ListingSubscriber implements EventSubscriberInterface
  12. {
  13.     private EntityRepository $productRepository;
  14.     private LoggerInterface $logger;
  15.     public function __construct(
  16.         EntityRepository $productRepository,
  17.         LoggerInterface $logger
  18.     ) {
  19.         $this->productRepository $productRepository;
  20.         $this->logger $logger;
  21.     }
  22.     public static function getSubscribedEvents(): array
  23.     {
  24.         return [
  25.             ProductListingResultEvent::class => ['onProductListingResult', -10],
  26.         ];
  27.     }
  28.     public function onProductListingResult(ProductListingResultEvent $event): void
  29.     {
  30.         $products $event->getResult()->getEntities();
  31.         foreach ($products as $product) {
  32.             if (!$product->getParentId()) {
  33.                 continue;
  34.             }
  35.             try {
  36.                 $criteria = new Criteria([$product->getParentId()]);
  37.                 $criteria->addAssociation('options.group')
  38.                         ->addAssociation('children')
  39.                         ->addAssociation('children.options.group')
  40.                         ->addAssociation('children.seoUrls');
  41.                 $parentProduct $this->productRepository->search(
  42.                     $criteria
  43.                     $event->getSalesChannelContext()->getContext()
  44.                 )->first();
  45.                 if (!$parentProduct) {
  46.                     continue;
  47.                 }
  48.                 $colorVariants $this->getColorVariants($parentProduct);
  49.                 $product->addExtension('colorVariants'$colorVariants);
  50.             } catch (\Exception $e) {
  51.                 $this->logger->error('Exception occurred when loading variants in product listing result: ' .
  52.                     $e->getMessage() . ",\nStack trace: " $e->getTraceAsString());
  53.             }
  54.         }
  55.     }
  56.     private function getColorVariants($parentProduct): ColorVariantCollection
  57.     {
  58.         $colorVariants = new ColorVariantCollection();
  59.         $children $parentProduct->getChildren();
  60.         $processedColors = []; // Track processed colors
  61.         if (!$children) {
  62.             return $colorVariants;
  63.         }
  64.         foreach ($children as $variant) {
  65.             $options $variant->getOptions();
  66.             if (!$options) {
  67.                 continue;
  68.             }
  69.             foreach ($options as $option) {
  70.                 $group $option->getGroup();
  71.                 if (!$group) {
  72.                     continue;
  73.                 }
  74.                 if (
  75.                     ($group->getDisplayType() === 'color' || 
  76.                     strtolower($group->getTranslation('name')) === 'color')
  77.                     && $variant->getAvailable() && $variant->getActive() // Only add available variants
  78.                 ) {
  79.                     // Create unique key based on color name and hex code
  80.                     $colorKey $option->getName() . '-' $option->getColorHexCode();
  81.                     
  82.                     // Skip if we've already processed this color
  83.                     if (isset($processedColors[$colorKey])) {
  84.                         continue;
  85.                     }
  86.                     $colorVariants->add(new ColorVariantStruct(
  87.                         $variant->getId(),
  88.                         $option->getTranslation('name'),
  89.                         $option->getColorHexCode(),
  90.                         $variant->getAvailable(),
  91.                         $variant->getStock()
  92.                     ));
  93.                     // Mark this color as processed
  94.                     $processedColors[$colorKey] = true;
  95.                 }
  96.             }
  97.         }
  98.         return $colorVariants;
  99.     }