Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 43 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
MappingValidator | |
0.00% |
0 / 43 |
|
0.00% |
0 / 4 |
132 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
isNaturalSortConfigured | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
validate | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
56 | |||
compareMappingToActual | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 |
1 | <?php |
2 | |
3 | namespace CirrusSearch\Maintenance\Validators; |
4 | |
5 | use CirrusSearch\ElasticaErrorHandler; |
6 | use CirrusSearch\Maintenance\Plugins; |
7 | use CirrusSearch\Maintenance\Printer; |
8 | use Elastica\Exception\ExceptionInterface; |
9 | use Elastica\Index; |
10 | use Elastica\Mapping; |
11 | use MediaWiki\Language\RawMessage; |
12 | use MediaWiki\Status\Status; |
13 | use Wikimedia\Assert\Assert; |
14 | |
15 | class MappingValidator extends Validator { |
16 | /** |
17 | * @var Index |
18 | */ |
19 | private $index; |
20 | |
21 | /** |
22 | * @var string |
23 | */ |
24 | private $masterTimeout; |
25 | |
26 | /** |
27 | * @var bool |
28 | */ |
29 | private $optimizeIndexForExperimentalHighlighter; |
30 | |
31 | /** |
32 | * @var array |
33 | */ |
34 | private $availablePlugins; |
35 | |
36 | /** |
37 | * @var array |
38 | */ |
39 | private $mappingConfig; |
40 | |
41 | /** |
42 | * @todo this constructor takes way too much arguments - refactor |
43 | * |
44 | * @param Index $index |
45 | * @param string $masterTimeout |
46 | * @param bool $optimizeIndexForExperimentalHighlighter |
47 | * @param array $availablePlugins |
48 | * @param array $mappingConfig |
49 | * @param Printer|null $out |
50 | */ |
51 | public function __construct( |
52 | Index $index, |
53 | $masterTimeout, |
54 | $optimizeIndexForExperimentalHighlighter, |
55 | array $availablePlugins, |
56 | array $mappingConfig, |
57 | ?Printer $out = null |
58 | ) { |
59 | parent::__construct( $out ); |
60 | |
61 | $this->index = $index; |
62 | $this->masterTimeout = $masterTimeout; |
63 | $this->optimizeIndexForExperimentalHighlighter = $optimizeIndexForExperimentalHighlighter; |
64 | $this->availablePlugins = $availablePlugins; |
65 | // Could be supported, but prefer consistency |
66 | Assert::parameter( isset( $mappingConfig['properties'] ), '$mappingConfig', |
67 | 'Mapping types are no longer supported, properties must be top level' ); |
68 | $this->mappingConfig = $mappingConfig; |
69 | } |
70 | |
71 | private function isNaturalSortConfigured() { |
72 | // awkward much? |
73 | return isset( $this->mappingConfig['properties']['title']['fields']['natural_sort'] ); |
74 | } |
75 | |
76 | /** |
77 | * @return Status |
78 | */ |
79 | public function validate() { |
80 | $this->outputIndented( "Validating mappings..." ); |
81 | if ( $this->optimizeIndexForExperimentalHighlighter && |
82 | !Plugins::contains( 'experimental-highlighter', $this->availablePlugins ) |
83 | ) { |
84 | $this->output( "impossible!\n" ); |
85 | return Status::newFatal( new RawMessage( |
86 | "wgCirrusSearchOptimizeIndexForExperimentalHighlighter is set to true but the " . |
87 | "'experimental-highlighter' plugin is not installed on all hosts." ) ); |
88 | } |
89 | if ( $this->isNaturalSortConfigured() && |
90 | !Plugins::contains( 'analysis-icu', $this->availablePlugins ) ) { |
91 | $this->output( "impossible!\n" ); |
92 | return Status::newFatal( new RawMessage( |
93 | "wgCirrusSearchNaturalTitleSort is set to build but the " . |
94 | "'analysis-icu' plugin is not installed on all hosts." ) ); |
95 | } |
96 | |
97 | if ( !$this->compareMappingToActual() ) { |
98 | $action = new Mapping( $this->mappingConfig['properties'] ); |
99 | $action->setParam( "dynamic", false ); |
100 | |
101 | try { |
102 | $action->send( $this->index, [ |
103 | 'master_timeout' => $this->masterTimeout, |
104 | ] ); |
105 | $this->output( "corrected\n" ); |
106 | } catch ( ExceptionInterface $e ) { |
107 | $this->output( "failed!\n" ); |
108 | $message = ElasticaErrorHandler::extractMessage( $e ); |
109 | return Status::newFatal( new RawMessage( |
110 | "Couldn't update existing mappings. You may need to reindex.\nHere is elasticsearch's error message: $message\n" ) ); |
111 | } |
112 | } |
113 | |
114 | return Status::newGood(); |
115 | } |
116 | |
117 | /** |
118 | * Check that the mapping returned from Elasticsearch is as we want it. |
119 | * |
120 | * @return bool is the mapping good enough for us? |
121 | */ |
122 | private function compareMappingToActual() { |
123 | $actualMappings = $this->index->getMapping(); |
124 | $this->output( "\n" ); |
125 | $this->outputIndented( "\tValidating mapping..." ); |
126 | if ( $this->checkConfig( $actualMappings, $this->mappingConfig ) ) { |
127 | $this->output( "ok\n" ); |
128 | return true; |
129 | } else { |
130 | $this->output( "different..." ); |
131 | return false; |
132 | } |
133 | } |
134 | } |