Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.59% covered (success)
94.59%
35 / 37
81.82% covered (warning)
81.82%
9 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
InLabelFilterVisitor
94.59% covered (success)
94.59%
35 / 37
81.82% covered (warning)
81.82%
9 / 11
16.04
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getFilterQuery
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 updateFilterQuery
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
5
 visitWordsQueryNode
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
2
 visitPhraseQueryNode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 visitPhrasePrefixNode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 visitFuzzyNode
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 visitPrefixNode
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 visitWildcardNode
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 visitEmptyQueryNode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 visitKeywordFeatureNode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php declare( strict_types=1 );
2
3namespace Wikibase\Search\Elastic\Query;
4
5use CirrusSearch\Parser\AST\BooleanClause;
6use CirrusSearch\Parser\AST\EmptyQueryNode;
7use CirrusSearch\Parser\AST\FuzzyNode;
8use CirrusSearch\Parser\AST\KeywordFeatureNode;
9use CirrusSearch\Parser\AST\PhrasePrefixNode;
10use CirrusSearch\Parser\AST\PhraseQueryNode;
11use CirrusSearch\Parser\AST\PrefixNode;
12use CirrusSearch\Parser\AST\Visitor\LeafVisitor;
13use CirrusSearch\Parser\AST\WildcardNode;
14use CirrusSearch\Parser\AST\WordsQueryNode;
15use Elastica\Query\AbstractQuery;
16use Elastica\Query\BoolQuery;
17use Elastica\Query\MatchPhrase;
18use Elastica\Query\MatchQuery;
19use Wikibase\Search\Elastic\Fields\AllLabelsField;
20use Wikibase\Search\Elastic\Fields\LabelsField;
21
22/**
23 * @license GPL-2.0-or-later
24 */
25class InLabelFilterVisitor extends LeafVisitor {
26    private const ALL_LABELS_FIELD = AllLabelsField::NAME . '.plain';
27
28    private AbstractQuery $filterQuery;
29    private string $languageCode;
30    private array $stemmingSettings;
31
32    public function __construct( string $languageCode, array $stemmingSettings ) {
33        parent::__construct();
34        $this->filterQuery = new BoolQuery();
35        $this->languageCode = $languageCode;
36        $this->stemmingSettings = $stemmingSettings;
37    }
38
39    public function getFilterQuery(): AbstractQuery {
40        return $this->filterQuery;
41    }
42
43    private function updateFilterQuery( AbstractQuery $query ) {
44        if ( $this->getCurrentBooleanClause() ) {
45            switch ( $this->getCurrentBooleanClause()->getOccur() ) {
46                case BooleanClause::SHOULD:
47                    $this->filterQuery->addShould( $query );
48                    break;
49                case BooleanClause::MUST:
50                    $this->filterQuery->addMust( $query );
51                    break;
52                case BooleanClause::MUST_NOT:
53                    $this->filterQuery->addMustNot( $query );
54                    break;
55            }
56        } else {
57            $this->filterQuery = $query;
58        }
59    }
60
61    /** @inheritDoc */
62    public function visitWordsQueryNode( WordsQueryNode $node ) {
63        $filter = new BoolQuery();
64        $filter->setMinimumShouldMatch( 1 );
65
66        $matchQuery = new MatchQuery( self::ALL_LABELS_FIELD, [ 'query' => $node->getWords() ] );
67        $matchQuery->setFieldOperator( self::ALL_LABELS_FIELD, MatchQuery::OPERATOR_AND );
68        $filter->addShould( $matchQuery );
69
70        if ( !empty( $this->stemmingSettings[$this->languageCode]['query'] ) ) {
71            $stemFilter = new MatchQuery( LabelsField::NAME . '.' . $this->languageCode, [ 'query' => $node->getWords() ] );
72            $stemFilter->setFieldOperator( LabelsField::NAME . '.' . $this->languageCode, MatchQuery::OPERATOR_AND );
73            $filter->addShould( $stemFilter );
74        }
75
76        $this->updateFilterQuery( $filter );
77    }
78
79    /** @inheritDoc    */
80    public function visitPhraseQueryNode( PhraseQueryNode $node ) {
81        $this->updateFilterQuery( new MatchPhrase( self::ALL_LABELS_FIELD, $node->getPhrase() ) );
82    }
83
84    /** @inheritDoc    */
85    public function visitPhrasePrefixNode( PhrasePrefixNode $node ) {
86        $this->updateFilterQuery( new MatchPhrase( self::ALL_LABELS_FIELD, $node->getPhrase() ) );
87    }
88
89    /** @inheritDoc    */
90    public function visitFuzzyNode( FuzzyNode $node ) {
91        $matchQuery = new MatchQuery( self::ALL_LABELS_FIELD, [ 'query' => $node->getWord() ] );
92        $matchQuery->setFieldOperator( self::ALL_LABELS_FIELD, MatchQuery::OPERATOR_AND );
93        $this->updateFilterQuery( $matchQuery );
94    }
95
96    /** @inheritDoc    */
97    public function visitPrefixNode( PrefixNode $node ) {
98        $matchQuery = new MatchQuery( self::ALL_LABELS_FIELD, [ 'query' => $node->getPrefix() ] );
99        $matchQuery->setFieldOperator( self::ALL_LABELS_FIELD, MatchQuery::OPERATOR_AND );
100        $this->updateFilterQuery( $matchQuery );
101    }
102
103    /** @inheritDoc    */
104    public function visitWildcardNode( WildcardNode $node ) {
105        $matchQuery = new MatchQuery( self::ALL_LABELS_FIELD, [ 'query' => $node->getWildcardQuery() ] );
106        $matchQuery->setFieldOperator( self::ALL_LABELS_FIELD, MatchQuery::OPERATOR_AND );
107        $this->updateFilterQuery( $matchQuery );
108    }
109
110    /** @inheritDoc    */
111    public function visitEmptyQueryNode( EmptyQueryNode $node ) {
112    }
113
114    /** @inheritDoc    */
115    public function visitKeywordFeatureNode( KeywordFeatureNode $node ) {
116    }
117}