vendor/store.shopware.com/moorlmagazine/src/Core/Content/MagazineArticle/SalesChannel/Listing/MagazineArticleListingFeaturesSubscriber.php line 62

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