vendor/store.shopware.com/moorlcreator/src/Core/Content/Creator/SalesChannel/Listing/CreatorListingFeaturesSubscriber.php line 73

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace MoorlCreator\Core\Content\Creator\SalesChannel\Listing;
  3. use Doctrine\DBAL\Connection;
  4. use MoorlCreator\Core\Content\Creator\CreatorDefinition;
  5. use MoorlCreator\Core\Content\Creator\SalesChannel\Events\CreatorListingCriteriaEvent;
  6. use MoorlCreator\Core\Content\Creator\SalesChannel\Events\CreatorListingResultEvent;
  7. use MoorlCreator\Core\Content\Creator\SalesChannel\Events\CreatorSearchCriteriaEvent;
  8. use MoorlCreator\Core\Content\Creator\SalesChannel\Events\CreatorSearchResultEvent;
  9. use MoorlCreator\Core\Content\Creator\SalesChannel\Events\CreatorSuggestCriteriaEvent;
  10. use MoorlFoundation\Core\Content\Sorting\SortingCollection;
  11. use MoorlFoundation\Core\Service\SortingService;
  12. use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
  13. use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
  14. use Shopware\Core\Content\Product\SalesChannel\Listing\FilterCollection;
  15. use Shopware\Core\Content\Product\SalesChannel\Sorting\ProductSortingEntity;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\FilterAggregation;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  18. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  19. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  20. use Symfony\Component\HttpFoundation\Request;
  21. class CreatorListingFeaturesSubscriber implements EventSubscriberInterface
  22. {
  23.     public const DEFAULT_SEARCH_SORT 'standard';
  24.     private SortingService $sortingService;
  25.     public function __construct(SortingService $sortingService)
  26.     {
  27.         $this->sortingService $sortingService;
  28.     }
  29.     public static function getSubscribedEvents(): array
  30.     {
  31.         return [
  32.             CreatorListingCriteriaEvent::class => [
  33.                 ['handleListingRequest'100],
  34.                 ['handleFlags', -100],
  35.             ],
  36.             CreatorSuggestCriteriaEvent::class => [
  37.                 ['handleFlags', -100],
  38.             ],
  39.             CreatorSearchCriteriaEvent::class => [
  40.                 ['handleSearchRequest'100],
  41.                 ['handleFlags', -100],
  42.             ],
  43.             CreatorListingResultEvent::class => [
  44.                 ['handleResult'100]
  45.             ],
  46.             CreatorSearchResultEvent::class => 'handleResult',
  47.         ];
  48.     }
  49.     public function handleFlags(ProductListingCriteriaEvent $event): void
  50.     {
  51.         $request $event->getRequest();
  52.         $criteria $event->getCriteria();
  53.         if ($request->get('no-aggregations')) {
  54.             $criteria->resetAggregations();
  55.         }
  56.         if ($request->get('only-aggregations')) {
  57.             $criteria->setLimit(0);
  58.             $criteria->setTotalCountMode(Criteria::TOTAL_COUNT_MODE_NONE);
  59.             $criteria->resetSorting();
  60.             $criteria->resetAssociations();
  61.         }
  62.     }
  63.     public function handleListingRequest(ProductListingCriteriaEvent $event): void
  64.     {
  65.         $request $event->getRequest();
  66.         $criteria $event->getCriteria();
  67.         $context $event->getSalesChannelContext();
  68.         if (!$request->get('order')) {
  69.             $request->request->set('order'self::DEFAULT_SEARCH_SORT);
  70.         }
  71.         $this->handlePagination($request$criteria$event->getSalesChannelContext());
  72.         $this->handleFilters($request$criteria$context);
  73.         $this->handleSorting($request$criteria$context);
  74.     }
  75.     public function handleSearchRequest(ProductListingCriteriaEvent $event): void
  76.     {
  77.         $request $event->getRequest();
  78.         $criteria $event->getCriteria();
  79.         $context $event->getSalesChannelContext();
  80.         if (!$request->get('order')) {
  81.             $request->request->set('order'self::DEFAULT_SEARCH_SORT);
  82.         }
  83.         $this->handlePagination($request$criteria$event->getSalesChannelContext());
  84.         $this->handleFilters($request$criteria$context);
  85.         $this->handleSorting($request$criteria$context);
  86.     }
  87.     public function handleResult(ProductListingResultEvent $event): void
  88.     {
  89.         $this->addCurrentFilters($event);
  90.         $result $event->getResult();
  91.         $sortings $this->sortingService->getAvailableSortings(
  92.             CreatorDefinition::ENTITY_NAME,
  93.             $event->getSalesChannelContext()->getContext()
  94.         );
  95.         $currentSortingKey $this->getCurrentSorting($sortings$event->getRequest())->getKey();
  96.         $result->setSorting($currentSortingKey);
  97.         $result->setAvailableSortings($sortings);
  98.         $result->setPage($this->getPage($event->getRequest()));
  99.         $result->setLimit($this->getLimit($event->getRequest()));
  100.     }
  101.     private function handleFilters(Request $requestCriteria $criteriaSalesChannelContext $context): void
  102.     {
  103.         $filters $this->getFilters($request$context);
  104.         $aggregations $this->getAggregations($request$filters);
  105.         foreach ($aggregations as $aggregation) {
  106.             $criteria->addAggregation($aggregation);
  107.         }
  108.         if ($request->get('search')) {
  109.             $criteria->setTerm($request->get('search'));
  110.         }
  111.         foreach ($filters as $filter) {
  112.             if ($filter->isFiltered()) {
  113.                 $criteria->addPostFilter($filter->getFilter());
  114.             }
  115.         }
  116.         $criteria->addExtension('filters'$filters);
  117.     }
  118.     private function getAggregations(Request $requestFilterCollection $filters): array
  119.     {
  120.         $aggregations = [];
  121.         if ($request->get('reduce-aggregations') === null) {
  122.             foreach ($filters as $filter) {
  123.                 $aggregations array_merge($aggregations$filter->getAggregations());
  124.             }
  125.             return $aggregations;
  126.         }
  127.         foreach ($filters as $filter) {
  128.             $excluded $filters->filtered();
  129.             if ($filter->exclude()) {
  130.                 $excluded $excluded->blacklist($filter->getName());
  131.             }
  132.             foreach ($filter->getAggregations() as $aggregation) {
  133.                 if ($aggregation instanceof FilterAggregation) {
  134.                     $aggregation->addFilters($excluded->getFilters());
  135.                     $aggregations[] = $aggregation;
  136.                     continue;
  137.                 }
  138.                 $aggregation = new FilterAggregation(
  139.                     $aggregation->getName(),
  140.                     $aggregation,
  141.                     $excluded->getFilters()
  142.                 );
  143.                 $aggregations[] = $aggregation;
  144.             }
  145.         }
  146.         return $aggregations;
  147.     }
  148.     private function handlePagination(Request $requestCriteria $criteriaSalesChannelContext $context): void
  149.     {
  150.         $limit $this->getLimit($request);
  151.         $page $this->getPage($request);
  152.         $criteria->setOffset(($page 1) * $limit);
  153.         $criteria->setLimit($limit);
  154.         $criteria->setTotalCountMode(Criteria::TOTAL_COUNT_MODE_EXACT);
  155.     }
  156.     private function handleSorting(Request $requestCriteria $criteriaSalesChannelContext $context): void
  157.     {
  158.         if ($criteria->getSorting()) {
  159.             return;
  160.         }
  161.         $sortings $this->sortingService->getAvailableSortings(
  162.             CreatorDefinition::ENTITY_NAME,
  163.             $context->getContext()
  164.         );
  165.         $currentSorting $this->getCurrentSorting($sortings$request);
  166.         $criteria->addSorting(...$currentSorting->createDalSorting());
  167.         $criteria->addExtension('sortings'$sortings);
  168.     }
  169.     private function getCurrentSorting(SortingCollection $sortingsRequest $request): ProductSortingEntity
  170.     {
  171.         $key $request->get('order');
  172.         $sorting $sortings->getByKey($key);
  173.         if ($sorting !== null) {
  174.             return $sorting;
  175.         }
  176.         return $sortings->first();
  177.     }
  178.     private function addCurrentFilters(ProductListingResultEvent $event): void
  179.     {
  180.         $result $event->getResult();
  181.         $filters $result->getCriteria()->getExtension('filters');
  182.         if (!$filters instanceof FilterCollection) {
  183.             return;
  184.         }
  185.         foreach ($filters as $filter) {
  186.             $result->addCurrentFilter($filter->getName(), $filter->getValues());
  187.         }
  188.     }
  189.     private function getLimit(Request $request): int
  190.     {
  191.         $limit $request->query->getInt('limit'0);
  192.         if ($request->isMethod(Request::METHOD_POST)) {
  193.             $limit $request->request->getInt('limit'$limit);
  194.         }
  195.         return $limit <= 12 $limit;
  196.     }
  197.     private function getPage(Request $request): int
  198.     {
  199.         $page $request->query->getInt('p'1);
  200.         if ($request->isMethod(Request::METHOD_POST)) {
  201.             $page $request->request->getInt('p'$page);
  202.         }
  203.         return $page <= $page;
  204.     }
  205.     private function getFilters(Request $requestSalesChannelContext $context): FilterCollection
  206.     {
  207.         return new FilterCollection();
  208.     }
  209. }