custom/plugins/MetalementsTheme/src/Subscriber/ProductVariantenMedia.php line 38

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace MetalementsTheme\Subscriber;
  4. use Shopware\Core\Framework\Struct\ArrayStruct;
  5. use Shopware\Core\Framework\Struct\ArrayEntity;
  6. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  7. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  11. use Shopware\Core\Content\Media\DataAbstractionLayer\MediaRepositoryDecorator;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  13. class ProductVariantenMedia implements EventSubscriberInterface
  14. {
  15.     private $productRepository;
  16.     private MediaRepositoryDecorator $mediaRepository;
  17.     private $allOptionsIds = [];
  18.     //this variable woll contain ,at the end, the options to be disabled 
  19.     private $optionsToBeDisabled = [];
  20.     public function __construct(EntityRepositoryInterface $productRepositoryMediaRepositoryDecorator $mediaRepository)
  21.     {
  22.         $this->productRepository $productRepository;
  23.         $this->mediaRepository $mediaRepository;
  24.     }
  25.     public static function getSubscribedEvents(): array
  26.     {
  27.         return [
  28.             ProductPageLoadedEvent::class => 'onProductPageLoaded'
  29.         ];
  30.     }
  31.     public function onProductPageLoaded(ProductPageLoadedEvent $event): void
  32.     {
  33.         $productColor null;
  34.         $options_value null;
  35.         $allOptions = [];
  36.         $filteredVariants = [];
  37.         $product  $event->getPage()->getProduct();
  38.         $parentProduct $product->getParent();
  39.         if ($parentProduct !== null) {
  40.             $product $parentProduct;
  41.         }
  42.         $optionSorted $event->getPage()->getConfiguratorSettings(); // This gets the list of configuration, and how they are displayed in frontend, see file: configurator.html.twig
  43.         // if u want to change the priority of an option, for example u want to change the main option, u can change the order of the options in this variable: optionSortedIds. 
  44.         //Just bring the option to the [0] key. 
  45.         //OR change the order of options in frontend, you can do this on : Product > Varianten > Storefront-Darstellung > Anzege Reinfolge
  46.         foreach ($optionSorted as $propertyGroup) {
  47.             $optionSortedIds[] = $propertyGroup->getId();
  48.         }
  49.         $criteria = new Criteria();
  50.         $criteria->addFilter(new EqualsFilter(
  51.             'parentId',
  52.             $product->getParentId()
  53.         ));
  54.         $criteria->addAssociation('cover.media');
  55.         $criteria->addAssociation('options.group');
  56.         // retrieve all product variants
  57.         $products $this->productRepository->search($criteria$event->getContext());
  58.         $matchingVariants $products->getEntities()->getElements();
  59.         // find which options are selected, i.e. which 'Eigenschaften' does the current product have.
  60.         $NummberOfOptions 0;
  61.         foreach ($product->getOptions() as  $option) {
  62.             if (strpos($option->getGroup()->name'Design') === false) {
  63.                 $options_value[] = $option->name;
  64.                 $NummberOfOptions $NummberOfOptions 1;
  65.             }
  66.             $currentProductOptionIds[$option->groupId] = $option->id;
  67.         }
  68.         // then filter variants based on the selected 'Eigenschaften' 
  69.         $NummberOfOptionsThatMatch 0;
  70.         foreach ($matchingVariants as $variantProduct) {
  71.             $NummberOfOptionsThatMatch 0;
  72.             $allOptions[] = 'Product:';
  73.             foreach ($variantProduct->getOptions() as  $option) {
  74.                 if (in_array($option->name$options_value)) {
  75.                     $NummberOfOptionsThatMatch $NummberOfOptionsThatMatch 1;
  76.                 }
  77.                 $allOptions[] = $option->name;
  78.                 // these two if statements will save all options of the all available variants, in each separate group array
  79.                 // allOptionsIds is used for a better structure of the options
  80.                 if (!isset($this->allOptionsIds[$option->groupId])) {
  81.                     $this->allOptionsIds[$option->groupId] = [];
  82.                 }
  83.                 if (!in_array($option->id$this->allOptionsIds[$option->groupId])) {
  84.                     $this->allOptionsIds[$option->groupId][] = $option->id;
  85.                 }
  86.             }
  87.             if ($NummberOfOptionsThatMatch == $NummberOfOptions) {
  88.                 $filteredVariants[] = $variantProduct;
  89.             }
  90.         }
  91.  
  92.         // compine all options in one array, 
  93.         foreach ($this->allOptionsIds as $groupId => $optionIds) {
  94.             if ($groupId !== $optionSortedIds[0])
  95.                 $this->optionsToBeDisabled array_merge($this->optionsToBeDisabled$optionIds);
  96.         }
  97.  
  98.  
  99.         // Determine the options to be disabled 
  100.         foreach ($matchingVariants as $variantProduct) {
  101.             $variantProductOptionIds = [];
  102.             foreach ($variantProduct->getOptions() as  $option) {
  103.                 $variantProductOptionIds[$option->groupId] = $option->id;
  104.             }
  105.             if ($variantProduct->getId() != $product->getId()) // dont check the currently displayed product
  106.                 $this->checkOptions(
  107.                     $variantProductOptionIds,
  108.                     $optionSortedIds,
  109.                     $currentProductOptionIds,
  110.                     $this->allOptionsIds,
  111.                     $this->optionsToBeDisabled,
  112.                     0,
  113.                     1
  114.                 );
  115.         }
  116.         $this->optionsToBeDisabled array_values($this->optionsToBeDisabled); // numerizes/cleans the array
  117.         foreach ($filteredVariants as $variant) {
  118.             $coverId $variant->getCover()->getMediaId();
  119.             if ($coverId) {
  120.                 $mediaCriteria = new Criteria();
  121.                 $mediaCriteria->addFilter(new EqualsFilter('id'$coverId));
  122.                 $mediaEntity $this->mediaRepository->search($mediaCriteria$event->getContext())->first();
  123.                 if ($mediaEntity) {
  124.                     $mediaEntity->addExtension('debugVariant'$variant);
  125.                     $variant->addExtension('variantMedia'$mediaEntity);
  126.                 }
  127.             }
  128.         }
  129.         $array = ['wct_product_varianten' => $filteredVariants];
  130.         $event->getPage()->assign($array);
  131.         $event->getPage()->assign(['all_options' => $allOptions]);
  132.         $event->getPage()->assign(['all_variants' => $matchingVariants]);
  133.         $event->getPage()->assign(['optionsToBeDisabled' =>  $this->optionsToBeDisabled]);
  134.         // die('<pre>'.print_r( $currentProductOptionIds , true).'</pre>');
  135.     }
  136.     function checkOptions($variantProductOptionIds$optionSortedIds,  $currentProductOptionIds$allOptionsIds, &$optionsToBeDisabled$n$m)
  137.     {
  138.         for ($i 0$i count($variantProductOptionIds); $i++) {
  139.             if (
  140.                 isset($optionSortedIds[$m]) &&
  141.                 isset($allOptionsIds[$optionSortedIds[$n]]) &&
  142.                 isset($allOptionsIds[$optionSortedIds[$m]]) &&
  143.                 $variantProductOptionIds[$optionSortedIds[$n]] === $currentProductOptionIds[$optionSortedIds[$n]] &&
  144.                 in_array($variantProductOptionIds[$optionSortedIds[$m]], $allOptionsIds[$optionSortedIds[$m]])
  145.             ) {
  146.                 $keyToRemove array_search($variantProductOptionIds[$optionSortedIds[$m]], $optionsToBeDisabled);
  147.                 if ($keyToRemove !== false) {
  148.                     unset($optionsToBeDisabled[$keyToRemove]);
  149.                 }
  150.                 $this->checkOptions(
  151.                     $variantProductOptionIds,
  152.                     $optionSortedIds,
  153.                     $currentProductOptionIds,
  154.                     $allOptionsIds,
  155.                     $optionsToBeDisabled,
  156.                     $n,
  157.                     $m
  158.                 );
  159.             }
  160.         }
  161.     }
  162. }