vendor/store.shopware.com/h1webblog/src/Subscriber/Search.php line 187

Open in your IDE?
  1. <?php
  2. namespace H1web\Blog\Subscriber;
  3. use H1web\Blog\Blog\BlogProductListingResult;
  4. use H1web\Blog\Blog\SalesChannel\BlogAvailableFilter;
  5. use H1web\Blog\Blog\SearchKeyword\BlogSearchTermInterpreter;
  6. use Shopware\Core\Content\Product\SalesChannel\Listing\ProductListingResult;
  7. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\AndFilter;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Query\ScoreQuery;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\RequestCriteriaBuilder;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Term\SearchPattern;
  15. use Shopware\Core\Framework\Routing\Exception\MissingRequestParameterException;
  16. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  17. use Shopware\Core\System\SystemConfig\SystemConfigService;
  18. use Shopware\Storefront\Page\Search\SearchPageLoadedEvent;
  19. use Shopware\Storefront\Page\Suggest\SuggestPageLoadedEvent;
  20. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  21. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  22. use Symfony\Component\HttpFoundation\Request;
  23. class Search implements EventSubscriberInterface
  24. {
  25.     /**
  26.      * Search constructor.
  27.      * @param EntityRepositoryInterface $blogRepository
  28.      * @param RequestCriteriaBuilder $criteriaBuilder
  29.      * @param SystemConfigService $systemConfigService
  30.      * @param BlogSearchTermInterpreter $interpreter
  31.      */
  32.     public function __construct(
  33.         EntityRepositoryInterface $blogRepository,
  34.         RequestCriteriaBuilder $criteriaBuilder,
  35.         SystemConfigService $systemConfigService,
  36.         BlogSearchTermInterpreter $interpreter
  37.     ) {
  38.         $this->blogRepository $blogRepository;
  39.         $this->criteriaBuilder $criteriaBuilder;
  40.         $this->systemConfigService $systemConfigService;
  41.         $this->interpreter $interpreter;
  42.     }
  43.     /**
  44.      * @return string[]
  45.      */
  46.     public static function getSubscribedEvents(): array
  47.     {
  48.         return [
  49.             SearchPageLoadedEvent::class => "onSearch",
  50.             SuggestPageLoadedEvent::class => "onSuggest"
  51.         ];
  52.     }
  53.     //Stolen from ProductListingFeaturesSubscriber because DRY, unless ShopWare
  54.     private function getLimit(Request $requestSalesChannelContext $context): int
  55.     {
  56.         $limit $request->query->getInt('limit'0);
  57.         if ($request->isMethod(Request::METHOD_POST)) {
  58.             $limit $request->request->getInt('limit'$limit);
  59.         }
  60.         $limit $limit $limit $this->systemConfigService->getInt('core.listing.productsPerPage'$context->getSalesChannel()->getId());
  61.         return $limit <= 24 $limit;
  62.     }
  63.     //Stolen from ProductListingFeaturesSubscriber because DRY, unless ShopWare
  64.     private function getPage(Request $request): int
  65.     {
  66.         $page $request->query->getInt('p'1);
  67.         if ($request->isMethod(Request::METHOD_POST)) {
  68.             $page $request->request->getInt('p'$page);
  69.         }
  70.         return $page <= $page;
  71.     }
  72.     private function getCriteria(Request $requestSalesChannelContext $context): Criteria
  73.     {
  74.         $criteria = new Criteria();
  75.         $criteria->addFilter(new BlogAvailableFilter($context->getSalesChannelId(), $request->cookies->get("timezone")));
  76.         //Stolen from ProductSearchBuilder
  77.         $search $request->get('search');
  78.         if (is_array($search)) {
  79.             $term implode(' '$search);
  80.         } else {
  81.             $term = (string) $search;
  82.         }
  83.         $term trim($term);
  84.         if (empty($term)) {
  85.             throw new MissingRequestParameterException('search');
  86.         }
  87.         $pattern $this->interpreter->interpret($term$context->getContext());
  88.         foreach ($pattern->getTerms() as $searchTerm) {
  89.             $criteria->addQuery(
  90.                 new ScoreQuery(
  91.                     new EqualsFilter('h1webblog_blog.searchKeywords.keyword'$searchTerm->getTerm()),
  92.                     $searchTerm->getScore(),
  93.                     'h1webblog_blog.searchKeywords.ranking'
  94.                 )
  95.             );
  96.         }
  97.         $criteria->addQuery(
  98.             new ScoreQuery(
  99.                 new ContainsFilter('h1webblog_blog.searchKeywords.keyword'$pattern->getOriginal()->getTerm()),
  100.                 $pattern->getOriginal()->getScore(),
  101.                 'h1webblog_blog.searchKeywords.ranking'
  102.             )
  103.         );
  104.         if ($pattern->getBooleanClause() !== SearchPattern::BOOLEAN_CLAUSE_AND) {
  105.             $criteria->addFilter(new AndFilter([
  106.             new EqualsAnyFilter('h1webblog_blog.searchKeywords.keyword'array_values($pattern->getAllTerms())),
  107.             new EqualsFilter('h1webblog_blog.searchKeywords.languageId'$context->getContext()->getLanguageId())
  108.             ]));
  109.         } else {
  110.             foreach ($pattern->getTokenTerms() as $terms) {
  111.                 $criteria->addFilter(new AndFilter([
  112.                     new EqualsFilter('h1webblog_blog.searchKeywords.languageId'$context->getContext()->getLanguageId()),
  113.                     new EqualsAnyFilter('h1webblog_blog.searchKeywords.keyword'$terms),
  114.                 ]));
  115.             }
  116.         }
  117.         //Stolen from ProductListingFeaturesSubscriber
  118.         $limit $this->getLimit($request$context);
  119.         $page $this->getPage($request);
  120.         $criteria->setOffset(($page 1) * $limit);
  121.         $criteria->setLimit($limit);
  122.         $criteria->setTotalCountMode(Criteria::TOTAL_COUNT_MODE_EXACT);
  123.         $criteria->addAssociation('categories')
  124.             ->addAssociation('visibilities')
  125.             ->addAssociation('tags')
  126.             ->addAssociation('customFields')
  127.             ->addAssociation('properties')
  128.             ->addAssociation('properties.group');
  129.         return $criteria;
  130.     }
  131.     public function onSearch(SearchPageLoadedEvent $event): void
  132.     {
  133.         $saleChannelContext $event->getSalesChannelContext();
  134.         $salesChannelId$saleChannelContext->getSalesChannel()->getId();
  135.         if ($this->systemConfigService->get('H1webBlog.config.blogSearchResults'$salesChannelId)) {
  136.             return;
  137.         }
  138.         $page $event->getPage();
  139.         $criteria $this->getCriteria($event->getRequest(), $event->getSalesChannelContext());
  140.         $blogs $this->blogRepository->search($criteria$event->getContext());
  141.         $page->addExtension("blogpages"$blogs);
  142.         //Allow further pagination if need be
  143.         $listing $page->getListing();
  144.         $total $listing->getTotal();
  145.         if ($total $blogs->getTotal()) {
  146.             $total $blogs->getTotal();
  147.         }
  148.         //Hack for the silly SearchController::search assumes a product result
  149.         if ($total == && $blogs->getTotal() == 1) {
  150.             $total 2;
  151.         }
  152.         $listingOld $listing;
  153.         //Hack to change pagination to our wishes
  154.         $listing BlogProductListingResult::createFrom($listing);
  155.         $listing->setTotal($total);
  156.         $page->setListing($listing);
  157.     }
  158.     public function onSuggest(SuggestPageLoadedEvent $event): void
  159.     {
  160.         $page $event->getPage();
  161.         $criteria $this->getCriteria($event->getRequest(), $event->getSalesChannelContext());
  162.         $criteria->setLimit(10);
  163.         $blogs $this->blogRepository->search($criteria$event->getContext());
  164.         $page->addExtension("blogpages"$blogs);
  165.     }
  166. }