Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
MappingValidator
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 3
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 validate
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
30
 compareMappingToActual
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace CirrusSearch\Maintenance\Validators;
4
5use CirrusSearch\ElasticaErrorHandler;
6use CirrusSearch\Maintenance\Printer;
7use CirrusSearch\Util;
8use Elastica\Exception\ExceptionInterface;
9use Elastica\Index;
10use Elastica\Mapping;
11use RawMessage;
12use Status;
13use Wikimedia\Assert\Assert;
14
15class 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    /**
72     * @return Status
73     */
74    public function validate() {
75        $this->outputIndented( "Validating mappings..." );
76        if ( $this->optimizeIndexForExperimentalHighlighter &&
77            !in_array( 'experimental-highlighter', $this->availablePlugins ) ) {
78            $this->output( "impossible!\n" );
79            return Status::newFatal( new RawMessage(
80                "wgCirrusSearchOptimizeIndexForExperimentalHighlighter is set to true but the " .
81                "'experimental-highlighter' plugin is not installed on all hosts." ) );
82        }
83
84        if ( !$this->compareMappingToActual() ) {
85            $action = new Mapping( $this->mappingConfig['properties'] );
86            $action->setParam( "dynamic", false );
87
88            try {
89                $action->send( $this->index, [
90                    'master_timeout' => $this->masterTimeout,
91                    'include_type_name' => 'false',
92                ] );
93                $this->output( "corrected\n" );
94            } catch ( ExceptionInterface $e ) {
95                $this->output( "failed!\n" );
96                $message = ElasticaErrorHandler::extractMessage( $e );
97                return Status::newFatal( new RawMessage(
98                    "Couldn't update existing mappings. You may need to reindex.\nHere is elasticsearch's error message: $message\n" ) );
99            }
100        }
101
102        return Status::newGood();
103    }
104
105    /**
106     * Check that the mapping returned from Elasticsearch is as we want it.
107     *
108     * @return bool is the mapping good enough for us?
109     */
110    private function compareMappingToActual() {
111        $actualMappings = Util::getIndexMapping( $this->index );
112        $this->output( "\n" );
113        $this->outputIndented( "\tValidating mapping..." );
114        if ( $this->checkConfig( $actualMappings, $this->mappingConfig ) ) {
115            $this->output( "ok\n" );
116            return true;
117        } else {
118            $this->output( "different..." );
119            return false;
120        }
121    }
122}