Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
FieldIterator
0.00% covered (danger)
0.00%
0 / 39
0.00% covered (danger)
0.00%
0 / 3
182
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
2
 getLanguageAgnosticQueries
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
20
 getLanguageAwareQueries
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2
3namespace Wikibase\MediaInfo\Search\ASTQueryBuilder;
4
5use ArrayIterator;
6
7class FieldIterator extends ArrayIterator {
8    public const LANGUAGE_AWARE_FIELDS = [
9        'descriptions.$language',
10        'descriptions.$language.plain',
11    ];
12
13    public const LANGUAGE_AGNOSTIC_FIELDS = [
14        'title',
15        'title.plain',
16        'category',
17        'category.plain',
18        'redirect.title',
19        'redirect.title.plain',
20        'heading',
21        'heading.plain',
22        'auxiliary_text',
23        'auxiliary_text.plain',
24        'text',
25        'text.plain',
26        'file_text',
27        'file_text.plain',
28        'suggest',
29    ];
30
31    public const STEMMED_TO_PLAIN_FIELDS_MAP = [
32        'descriptions.$language' => 'descriptions.$language.plain',
33        'title' => 'title.plain',
34        'category' => 'category.plain',
35        'redirect.title' => 'redirect.title.plain',
36        'heading' => 'heading.plain',
37        'auxiliary_text' => 'auxiliary_text.plain',
38        'text' => 'text.plain',
39        'file_text' => 'file_text.plain',
40    ];
41
42    public const STEMMED_FIELDS = [
43        'descriptions.$language',
44        'title',
45        'category',
46        'redirect.title',
47        'heading',
48        'auxiliary_text',
49        'text',
50        'file_text',
51    ];
52
53    public const PLAIN_FIELDS = [
54        'descriptions.$language.plain',
55        'title.plain',
56        'category.plain',
57        'redirect.title.plain',
58        'heading.plain',
59        'auxiliary_text.plain',
60        'text.plain',
61        'file_text.plain',
62        'suggest',
63    ];
64
65    /** @var fieldQueryBuilderInterface */
66    private $fieldQueryBuilder;
67
68    /** @var string[] */
69    private $fields;
70
71    /** @var string[] */
72    private $languages;
73
74    /** @var array[] */
75    private $stemmingSettings;
76
77    /** @var float[] */
78    private $boosts;
79
80    /** @var float[] */
81    private $decays;
82
83    public function __construct(
84        fieldQueryBuilderInterface $fieldQueryBuilder,
85        array $fields,
86        array $languages,
87        array $stemmingSettings,
88        array $boosts,
89        array $decays
90    ) {
91        $this->fieldQueryBuilder = $fieldQueryBuilder;
92        $this->fields = $fields;
93        $this->languages = $languages;
94        $this->stemmingSettings = $stemmingSettings;
95        $this->boosts = $boosts;
96        $this->decays = $decays;
97
98        parent::__construct(
99            array_merge(
100                $this->getLanguageAgnosticQueries(),
101                $this->getLanguageAwareQueries()
102            )
103        );
104    }
105
106    private function getLanguageAgnosticQueries(): array {
107        $fields = array_intersect( static::LANGUAGE_AGNOSTIC_FIELDS, $this->fields );
108
109        $queries = [];
110        foreach ( $fields as $field ) {
111            $boost = $this->boosts[$field] ?: 0;
112            if ( $boost > 0 ) {
113                $queries[] = $this->fieldQueryBuilder->getQuery( $field, $boost );
114            }
115        }
116        return $queries;
117    }
118
119    private function getLanguageAwareQueries(): array {
120        $queries = [];
121
122        $fields = array_intersect( static::LANGUAGE_AWARE_FIELDS, $this->fields );
123        foreach ( $this->languages as $index => $language ) {
124
125            $stemmingEnabledForLanguage = $this->stemmingSettings[$language]['query'] ?? false;
126
127            foreach ( $fields as $field ) {
128                // decay x% for each fallback language
129                $boost = ( $this->boosts[$field] ?? 0 ) * ( ( $this->decays[$field] ?? 1 ) ** $index );
130
131                if ( $boost > 0 ) {
132                    if (
133                        // if stemming is turned on for this language
134                        $stemmingEnabledForLanguage ||
135                        // or if this field is not a stemmed field
136                        !in_array( $field, static::STEMMED_FIELDS )
137                    ) {
138                        // parse the language into the field name
139                        $field = str_replace( '$language', $language, $field );
140                        $queries[] = $this->fieldQueryBuilder->getQuery( $field, $boost );
141                    } else {
142                        // Otherwise
143                        // - this field IS a stemmed field
144                        // - we do NOT have stemming turned on for this language
145                        // ... and therefore we cannot query the field.
146                        // Deal with this by checking if there's a plain equivalent of the stemmed
147                        // field that has no boost of its own, and if there is then query the plain
148                        // field instead
149                        if ( isset( static::STEMMED_TO_PLAIN_FIELDS_MAP[$field] ) ) {
150                            $plainField = static::STEMMED_TO_PLAIN_FIELDS_MAP[$field];
151                            $plainBoost =
152                                ( $this->boosts[$plainField] ?? 0 ) *
153                                ( ( $this->decays[$plainField] ?? 1 ) ** $index );
154                            if ( $plainBoost == 0 ) {
155                                $plainField = str_replace( '$language', $language, $plainField );
156                                $queries[] = $this->fieldQueryBuilder->getQuery( $plainField, $boost );
157                            }
158                        }
159                    }
160                }
161            }
162        }
163        return $queries;
164    }
165}