Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
WikibaseEntitiesHandler
0.00% covered (danger)
0.00%
0 / 50
0.00% covered (danger)
0.00%
0 / 3
380
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 transform
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 1
306
 getFieldMatch
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Wikibase\MediaInfo\Search\ASTQueryBuilder;
4
5use CirrusSearch\Parser\AST\ParsedNode;
6use CirrusSearch\Parser\AST\ParsedQuery;
7use Elastica\Query\AbstractQuery;
8use Elastica\Query\BoolQuery;
9use Elastica\Query\DisMax;
10use Elastica\Query\MatchNone;
11use Elastica\Query\MatchQuery;
12use Wikibase\MediaInfo\Search\MediaSearchASTEntitiesExtractor;
13use Wikibase\Search\Elastic\Fields\StatementsField;
14
15class WikibaseEntitiesHandler implements ParsedNodeHandlerInterface {
16    /** @var ParsedNode */
17    private $node;
18
19    /** @var ParsedQuery */
20    private $query;
21
22    /** @var MediaSearchASTEntitiesExtractor */
23    private $entitiesExtractor;
24
25    /** @var array */
26    private $boosts;
27
28    /** @var bool */
29    private $variableBoost;
30
31    public function __construct(
32        ParsedNode $node,
33        ParsedQuery $query,
34        MediaSearchASTEntitiesExtractor $entitiesExtractor,
35        array $boosts,
36        array $options
37    ) {
38        $this->node = $node;
39        $this->query = $query;
40        $this->entitiesExtractor = $entitiesExtractor;
41        $this->boosts = $boosts;
42        $this->variableBoost = $options['entitiesVariableBoost'];
43    }
44
45    public function transform(): AbstractQuery {
46        $entities = $this->entitiesExtractor->getEntities( $this->query, $this->node );
47        if ( count( $entities ) === 0 ) {
48            return new MatchNone();
49        }
50
51        $statementsQueries = [];
52        $weightedTagsQueries = [];
53
54        foreach ( $entities as $entity ) {
55            if ( $entity['score'] >= 0 ) {
56                foreach ( $this->boosts['statement'] ?? [] as $propertyId => $weight ) {
57                    $statementBoost = $this->variableBoost ? $weight * $entity['score'] : $weight;
58                    if ( $statementBoost > 0 ) {
59                        $statementsQueries[] = $this->getFieldMatch(
60                            StatementsField::NAME,
61                            $propertyId . StatementsField::STATEMENT_SEPARATOR . $entity['entityId'],
62                            $statementBoost
63                        );
64                    }
65                }
66            }
67
68            // ONLY do weighted_tags queries if we have an exact match
69            // weighted_tags is a very powerful search signal, so we want to be sure we're
70            // searching for the right thing
71            if ( $entity['score'] >= 1 ) {
72                foreach ( $this->boosts['weighted_tags'] ?? [] as $prefix => $weight ) {
73                    $weightedTagBoost = $this->variableBoost ? $weight * $entity['score'] : $weight;
74                    if ( $weightedTagBoost > 0 ) {
75                        $weightedTagsQueries[] = $this->getFieldMatch(
76                            'weighted_tags',
77                            $prefix . $entity['entityId'],
78                            $weightedTagBoost
79                        );
80                    }
81                }
82            }
83        }
84
85        $statementsQuery = new DisMax();
86        foreach ( $statementsQueries as $query ) {
87            $statementsQuery->addQuery( $query );
88        }
89        $weightedTagsQuery = new BoolQuery();
90        $weightedTagsQuery->setMinimumShouldMatch( 1 );
91        foreach ( $weightedTagsQueries as $query ) {
92            $weightedTagsQuery->addShould( $query );
93        }
94
95        if ( count( $statementsQueries ) === 0 && count( $weightedTagsQueries ) === 0 ) {
96            return new MatchNone();
97        }
98        if ( count( $weightedTagsQueries ) === 0 ) {
99            return $statementsQuery;
100        }
101        if ( count( $statementsQueries ) === 0 ) {
102            return $weightedTagsQuery;
103        }
104        $query = new BoolQuery();
105        $query->setMinimumShouldMatch( 1 );
106        $query->addShould( $statementsQuery );
107        $query->addShould( $weightedTagsQuery );
108        return $query;
109    }
110
111    private function getFieldMatch( string $field, string $query, float $boost ): MatchQuery {
112        return ( new MatchQuery() )
113            ->setFieldQuery( $field, $query )
114            ->setFieldBoost( $field, $boost );
115    }
116}