Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
24 / 24 |
|
100.00% |
2 / 2 |
CRAP | |
100.00% |
1 / 1 |
DefaultSearchQueryDispatchService | |
100.00% |
24 / 24 |
|
100.00% |
2 / 2 |
8 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
bestRoute | |
100.00% |
23 / 23 |
|
100.00% |
1 / 1 |
7 |
1 | <?php |
2 | |
3 | namespace CirrusSearch\Dispatch; |
4 | |
5 | use CirrusSearch\Profile\SearchProfileException; |
6 | use CirrusSearch\Search\SearchQuery; |
7 | use Wikimedia\Assert\Assert; |
8 | |
9 | class DefaultSearchQueryDispatchService implements SearchQueryDispatchService { |
10 | /** |
11 | * List of routes per search engine entry point |
12 | * @var SearchQueryRoute[][] indexed by search engine entry point |
13 | */ |
14 | private $routes; |
15 | |
16 | /** |
17 | * @param SearchQueryRoute[][] $routes |
18 | */ |
19 | public function __construct( array $routes ) { |
20 | $this->routes = $routes; |
21 | } |
22 | |
23 | /** |
24 | * @param SearchQuery $query |
25 | * @return SearchQueryRoute |
26 | */ |
27 | public function bestRoute( SearchQuery $query ): SearchQueryRoute { |
28 | Assert::parameter( isset( $this->routes[$query->getSearchEngineEntryPoint()] ), 'query', |
29 | "Unsupported search engine entry point {$query->getSearchEngineEntryPoint()}" ); |
30 | |
31 | $routes = $this->routes[$query->getSearchEngineEntryPoint()]; |
32 | |
33 | $bestScore = 0.0; |
34 | |
35 | /** @var SearchQueryRoute $best */ |
36 | $best = null; |
37 | foreach ( $routes as $route ) { |
38 | $score = $route->score( $query ); |
39 | Assert::postcondition( $score >= 0 && $score <= 1.0, "SearchQueryRoute scores must be between 0.0 and 1.0" ); |
40 | if ( $score === 0.0 ) { |
41 | continue; |
42 | } |
43 | if ( $score === 1.0 ) { |
44 | if ( $bestScore === 1.0 ) { |
45 | throw new SearchProfileException( "Two competing contexts " . |
46 | // @phan-suppress-next-line PhanNonClassMethodCall $best always set when reaching this line |
47 | "{$route->getProfileContext()} and {$best->getProfileContext()} " . |
48 | " produced the max score" ); |
49 | } |
50 | $bestScore = $score; |
51 | $best = $route; |
52 | } elseif ( $score > $bestScore ) { |
53 | $best = $route; |
54 | $bestScore = $score; |
55 | } |
56 | } |
57 | Assert::postcondition( $best !== null, |
58 | "No route to backend, make sure a default SearchQueryRoute is added for {$query->getSearchEngineEntryPoint()}" ); |
59 | return $best; |
60 | } |
61 | } |