custom/plugins/KsAdditions/src/Subscribers/Product/Listing/ListingSubscriber.php line 68

Open in your IDE?
  1. <?php
  2. namespace Ks\KsAdditions\Subscribers\Product\Listing;
  3. use Doctrine\DBAL\Connection;
  4. use Ks\KsAdditions\KsAdditions;
  5. use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
  6. use Shopware\Core\Content\Product\ProductEntity;
  7. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Metric\MaxAggregation;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Metric\MinAggregation;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  17. use Shopware\Core\Framework\Struct\ArrayStruct;
  18. use Shopware\Core\Framework\Uuid\Uuid;
  19. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  20. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  21. class ListingSubscriber implements EventSubscriberInterface
  22. {
  23.     /**
  24.      * @var EntityRepositoryInterface
  25.      */
  26.     private EntityRepositoryInterface $productRepository;
  27.     /**
  28.      * @var SalesChannelRepositoryInterface
  29.      */
  30.     private SalesChannelRepositoryInterface $salesChannelProductRepository;
  31.     /** @var Connection */
  32.     private $connection;
  33.     /**
  34.      * @param EntityRepositoryInterface $productRepository
  35.      * @param SalesChannelRepositoryInterface $salesChannelProductRepository
  36.      * @param Connection $connection
  37.      */
  38.     public function __construct(
  39.         EntityRepositoryInterface  $productRepository,
  40.         SalesChannelRepositoryInterface $salesChannelProductRepository,
  41.         Connection $connection
  42.     ) {
  43.         $this->productRepository $productRepository;
  44.         $this->salesChannelProductRepository $salesChannelProductRepository;
  45.         $this->connection $connection;
  46.     }
  47.     /**
  48.      * @return \array[][]
  49.      */
  50.     public static function getSubscribedEvents(): array
  51.     {
  52.         return [
  53.             ProductListingResultEvent::class => ['handleListingResult'0],
  54.         ];
  55.     }
  56.     /**
  57.      * @param ProductListingResultEvent $event
  58.      * @return void
  59.      */
  60.     public function handleListingResult(ProductListingResultEvent $event): void
  61.     {
  62.         $context $event->getContext();
  63.         $currentCategoryId $event->getResult()->getCurrentFilter('navigationId');
  64.         $criteria = new Criteria();
  65.         $criteria->addFilter(
  66.             new MultiFilter(
  67.                 MultiFilter::CONNECTION_AND,
  68.                 [
  69.                     new EqualsAnyFilter('categoryTree', [$currentCategoryId]),
  70.                     new RangeFilter('stock', [
  71.                         RangeFilter::GT => 0
  72.                     ]),
  73.                 ]
  74.             )
  75.         );
  76.         $criteria->addAggregation(
  77.             new MaxAggregation('max-passung''product.customFields.' KsAdditions::ADDVISOR_PASSUNG_MAX),
  78.             new MinAggregation('min-passung''product.customFields.' KsAdditions::ADDVISOR_PASSUNG_MIN),
  79.         );
  80.         $result $this->productRepository->search($criteria$context);
  81.         $event->getResult()->addExtension('passung', new ArrayStruct([
  82.             'max' => $result->getAggregations()->get('max-passung')->getMax(),
  83.             'min' => $result->getAggregations()->get('min-passung')->getMin(),
  84.         ]));
  85.         $currentPassung $event->getRequest()->get('passung');
  86.         if ($currentPassung) {
  87.             foreach ($event->getResult()->getEntities() as $product) {
  88.                 $bestVariant $this->findBestVariant($product, (int) $currentPassung$event->getSalesChannelContext());
  89.                 if ($bestVariant) {
  90.                     $product->assign(['KsBestVariant' => $bestVariant]);
  91.                 }
  92.             }
  93.         }
  94.     }
  95.     private function findBestVariant($product$currentPassung$salesChanneContext)
  96.     {
  97.         $criteria = new Criteria();
  98.         $criteria->addFilter(
  99.             new MultiFilter(
  100.                 MultiFilter::CONNECTION_AND,
  101.                 [
  102.                     new RangeFilter('stock', [
  103.                         RangeFilter::GT => 0
  104.                     ]),
  105.                     new RangeFilter('product.customFields.' KsAdditions::ADDVISOR_PASSUNG_MIN, [
  106.                         RangeFilter::LTE => $currentPassung
  107.                     ]),
  108.                     new RangeFilter('product.customFields.' KsAdditions::ADDVISOR_PASSUNG_MAX, [
  109.                         RangeFilter::GTE => $currentPassung
  110.                     ]),
  111.                 ]
  112.             )
  113.         );
  114.         if (!$product->getParentId()) {
  115.             $criteria->addFilter(new EqualsFilter('product.parentId'$product->getId()));
  116.         } else {
  117.             $criteria->addFilter(new EqualsFilter('product.parentId'$product->getParentId()));
  118.         }
  119.         $criteria->addSorting(new FieldSorting('product.stock'FieldSorting::DESCENDING));
  120.         $criteria->addAssociation('prices')
  121.             ->addAssociation('unit')
  122.             ->addAssociation('deliveryTime')
  123.             ->addAssociation('cover.media');
  124.         $result $this->salesChannelProductRepository->search($criteria$salesChanneContext);
  125.         return $result->getTotal() > $result->first() : null;
  126.     }
  127. }