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

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