Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
DefaultSearchQueryDispatchService
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
2 / 2
8
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 bestRoute
100.00% covered (success)
100.00%
23 / 23
100.00% covered (success)
100.00%
1 / 1
7
1<?php
2
3namespace CirrusSearch\Dispatch;
4
5use CirrusSearch\Profile\SearchProfileException;
6use CirrusSearch\Search\SearchQuery;
7use Wikimedia\Assert\Assert;
8
9class 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}