‪TYPO3CMS  ‪main
SearchRepository.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
26 
33 {
34  public function ‪__construct(
35  protected readonly EventDispatcherInterface $eventDispatcher,
36  protected readonly ‪SearchProviderRegistry $searchProviderRegistry,
37  ) {}
38 
45  public function getSearchProviderState(‪SearchDemand $searchDemand): array
46  {
48  foreach ($this->searchProviderRegistry->getProviders() as $searchProviderClassName => ‪$searchProvider) {
49  ‪$searchProviders[$searchProviderClassName] = [
50  'instance' => ‪$searchProvider,
51  'isActive' => in_array($searchProviderClassName, $searchDemand->‪getSearchProviders(), true),
52  ];
53  }
54 
56  }
57 
61  public function ‪getViableSearchProviders(‪SearchDemand $searchDemand): array
62  {
63  return array_filter(
64  $this->searchProviderRegistry->getProviders(),
65  static fn(‪SearchProviderInterface $provider): bool => $searchDemand->‪getSearchProviders() === [] || in_array(get_class($provider), $searchDemand->‪getSearchProviders(), true)
66  );
67  }
68 
69  public function ‪find(‪SearchDemand $searchDemand): ‪ArrayPaginator
70  {
71  $searchResults = [];
72  $totalCount = 0;
73  $mutableSearchDemand = ‪MutableSearchDemand::fromSearchDemand($searchDemand);
74  $offset = $searchDemand->‪getOffset();
75  $remainingItems = $searchDemand->‪getLimit();
76 
77  foreach ($this->‪getViableSearchProviders($searchDemand) as $provider) {
78  $count = $provider->count($mutableSearchDemand->freeze());
79  $totalCount += $count;
80  if ($count < $offset) {
81  // The number of potential results is smaller than the offset, do not query results
82  $offset -= $count;
83  continue;
84  }
85 
86  if ($remainingItems < 1) {
87  continue;
88  }
89 
90  $mutableSearchDemand
91  ->setProperty(DemandPropertyName::limit, $remainingItems)
92  ->setProperty(DemandPropertyName::offset, $offset);
93  $providerResult = $provider->find($mutableSearchDemand->freeze());
94  if ($providerResult !== []) {
95  foreach ($providerResult as $key => $resultItem) {
96  $modifyRecordEvent = $this->eventDispatcher->dispatch(new ‪ModifyResultItemInLiveSearchEvent($resultItem));
97  $providerResult[$key] = $modifyRecordEvent->getResultItem();
98  }
99  $remainingItems -= count($providerResult);
100  // We got a result here, offset became irrelevant for next iteration
101  $offset = 0;
102 
103  $searchResults[] = $providerResult;
104  }
105  }
106  unset($mutableSearchDemand);
107 
108  $flattenedSearchResults = array_merge([], ...$searchResults);
109  $resultCount = count($flattenedSearchResults);
110 
111  $currentPage = (int)floor(($searchDemand->‪getOffset() + $searchDemand->‪getLimit()) / $searchDemand->‪getLimit());
112  if (ceil($totalCount / $searchDemand->‪getLimit()) < $currentPage) {
113  // Requested page does not match with the overall amount of items, reset to first page
114  $currentPage = 1;
115  }
116 
117  if ($resultCount > 0) {
118  // The paginator expects a full result set to be able to calculate its pagination. This will have negative
119  // performance consequences, therefore we only consider the current result set and create stubs for the "gaps".
120  $paginatorItems = array_merge(
121  array_fill(0, $searchDemand->‪getOffset(), null),
122  $flattenedSearchResults,
123  array_fill(0, $totalCount - $searchDemand->‪getOffset() - $resultCount, null)
124  );
125  } else {
126  $paginatorItems = [];
127  }
128 
129  return new ‪ArrayPaginator($paginatorItems, $currentPage, ‪SearchDemand::DEFAULT_LIMIT);
130  }
131 }
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchProviderRegistry
Definition: SearchProviderRegistry.php:26
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchDemand\MutableSearchDemand\fromSearchDemand
‪static fromSearchDemand(SearchDemand $searchDemand)
Definition: MutableSearchDemand.php:25
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchDemand\SearchDemand\getSearchProviders
‪class string< SearchProviderInterface >[] getSearchProviders()
Definition: SearchDemand.php:84
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchRepository\find
‪find(SearchDemand $searchDemand)
Definition: SearchRepository.php:69
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchRepository\$searchProvider
‪array< class-string, function getSearchProviderState(SearchDemand $searchDemand):array { $searchProviders=[];foreach( $this->searchProviderRegistry->getProviders() as $searchProviderClassName=> $searchProvider) { $searchProviders[ $searchProviderClassName]=['instance'=> $searchProvider
Definition: SearchRepository.php:50
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchDemand\DemandPropertyName
‪DemandPropertyName
Definition: DemandPropertyName.php:21
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchRepository\getViableSearchProviders
‪SearchProviderInterface[] getViableSearchProviders(SearchDemand $searchDemand)
Definition: SearchRepository.php:61
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchRepository\$searchProviders
‪array< class-string, function getSearchProviderState(SearchDemand $searchDemand):array { $searchProviders=[];foreach( $this->searchProviderRegistry->getProviders() as $searchProviderClassName=> $searchProvider) { $searchProviders[ $searchProviderClassName]=['instance'=> return $searchProviders
Definition: SearchRepository.php:51
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchDemand\SearchDemand
Definition: SearchDemand.php:29
‪TYPO3\CMS\Backend\Search\LiveSearch
Definition: BackendModuleProvider.php:18
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchDemand\SearchDemand\getOffset
‪getOffset()
Definition: SearchDemand.php:76
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchRepository\__construct
‪__construct(protected readonly EventDispatcherInterface $eventDispatcher, protected readonly SearchProviderRegistry $searchProviderRegistry,)
Definition: SearchRepository.php:34
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchDemand\MutableSearchDemand
Definition: MutableSearchDemand.php:24
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchDemand\SearchDemand\DEFAULT_LIMIT
‪const DEFAULT_LIMIT
Definition: SearchDemand.php:30
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchRepository
Definition: SearchRepository.php:33
‪TYPO3\CMS\Core\Pagination\ArrayPaginator
Definition: ArrayPaginator.php:21
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchDemand\SearchDemand\getLimit
‪getLimit()
Definition: SearchDemand.php:71
‪TYPO3\CMS\Backend\Search\Event\ModifyResultItemInLiveSearchEvent
Definition: ModifyResultItemInLiveSearchEvent.php:26
‪TYPO3\CMS\Backend\Search\LiveSearch\SearchProviderInterface
Definition: SearchProviderInterface.php:28