EBernhardson has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/298111

Change subject: Refactor some state from Searcher::searchText to SearchContext
......................................................................

Refactor some state from Searcher::searchText to SearchContext

In preparation for refactoring parts of query parsing out of searchText
push some of the state into SearchContext. This should make it easier
to break parts out of the function.

Change-Id: Ie7a647163c4a9e0c6b61d461084cee31fe5d567e
---
A includes/Query/Feature.php
M includes/Search/Filters.php
M includes/Search/SearchContext.php
M includes/Searcher.php
4 files changed, 208 insertions(+), 137 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CirrusSearch 
refs/changes/11/298111/1

diff --git a/includes/Query/Feature.php b/includes/Query/Feature.php
new file mode 100644
index 0000000..a3eabd9
--- /dev/null
+++ b/includes/Query/Feature.php
@@ -0,0 +1,6 @@
+<?php
+
+namespace CirrusSearch\Query;
+
+interface Feature {
+}
diff --git a/includes/Search/Filters.php b/includes/Search/Filters.php
index 13094be..a404edd 100644
--- a/includes/Search/Filters.php
+++ b/includes/Search/Filters.php
@@ -120,8 +120,8 @@
         * @param string $value
         * @return callable a side-effecting function to update several 
references
         */
-       public static function insource( Escaper $escaper, SearchContext 
$context, $value ) {
-               return self::insourceOrIntitle( $escaper, $context, $value, 
true, function () {
+       public static function insource( Escaper $escaper, $value ) {
+               return self::insourceOrIntitle( $escaper, $value, true, 
function () {
                        return 'source_text.plain';
                });
        }
@@ -136,8 +136,8 @@
         * @param string $value
         * @return callable a side-effecting function to update several 
references
         */
-       public static function intitle( Escaper $escaper, SearchContext 
$context, $value ) {
-               return self::insourceOrIntitle( $escaper, $context, $value, 
false, function ( $queryString ) {
+       public static function intitle( Escaper $escaper, $value ) {
+               return self::insourceOrIntitle( $escaper, $value, false, 
function ( $queryString ) {
                        if ( preg_match( '/[?*]/u', $queryString ) ) {
                                return 'title.plain';
                        } else {
@@ -185,7 +185,7 @@
         * @param callable $fieldF
         * @return callable
         */
-       private static function insourceOrIntitle( Escaper $escaper, 
SearchContext $context, $value, $updateHighlightSourceRef, $fieldF ) {
+       private static function insourceOrIntitle( Escaper $escaper, $value, 
$updateHighlightSourceRef, $fieldF ) {
                list( $queryString, $fuzzyQuery ) = 
$escaper->fixupWholeQueryString(
                        $escaper->fixupQueryStringPart( $value ) );
                $field = $fieldF( $queryString );
@@ -197,14 +197,13 @@
                $query->setRewrite( 'top_terms_boost_1024' );
 
                $updateReferences =
-                       function ( &$fuzzyQueryRef, &$filterDestinationRef, 
&$highlightSourceRef, &$searchContainedSyntaxRef )
+                       function ( &$fuzzyQueryRef, &$filterDestinationRef, 
&$highlightSourceRef )
                             use ( $fuzzyQuery, $query, 
$updateHighlightSourceRef ) {
                                $fuzzyQueryRef             = $fuzzyQuery;
                                $filterDestinationRef[]    = $query;
                                if ($updateHighlightSourceRef) {
                                        $highlightSourceRef[]      = array( 
'query' => $query );
                                }
-                               $searchContainedSyntaxRef  = true;
                        };
 
                return $updateReferences;
diff --git a/includes/Search/SearchContext.php 
b/includes/Search/SearchContext.php
index eb2fbf7..5800cdb 100644
--- a/includes/Search/SearchContext.php
+++ b/includes/Search/SearchContext.php
@@ -41,17 +41,12 @@
        private $namespaces;
 
        /**
-        * @var boolean
-        */
-       private $searchContainedSyntax = false;
-
-       /**
         * @var SearchTextQueryBuilderFactory
         */
        private $searchTextQueryBuilderFactory;
 
        /**
-        * @var array list of boost templates extracted from the query string
+        * @var array|null list of boost templates extracted from the query 
string
         */
        private $boostTemplatesFromQuery;
 
@@ -83,6 +78,31 @@
         * coord, radius and weight. Used for geographic radius boosting.
         */
        private $geoBoosts = array();
+
+       /**
+        * @var bool Could this query possibly return results?
+        */
+       private $resultsPossible = true;
+
+       /**
+        * @var string[] List of features in the user suplied query string
+        */
+       private $syntaxUsed = array();
+
+       /**
+        * @var string The type of search being performed
+        */
+       private $searchType = 'unknown';
+
+       /**
+        * @var \Elastica\AbstractQuery[]
+        */
+       private $filters = array();
+
+       /**
+        * @var \Elastica\AbstractQuery[]
+        */
+       private $notFilters = array();
 
        /**
         * @param SearchConfig $config
@@ -127,20 +147,6 @@
         */
        public function isAllowLeadingWildcards() {
                return (bool) $this->config->get( 
'CirrusSearchAllowLeadingWildcard' );
-       }
-
-       /**
-        * @return true if the query contains special syntax
-        */
-       public function isSearchContainedSyntax() {
-               return $this->searchContainedSyntax;
-       }
-
-       /**
-        * @param bool $searchContainedSyntax true if the query contains 
special syntax
-        */
-       public function setSearchContainedSyntax( $searchContainedSyntax ) {
-               $this->searchContainedSyntax = $searchContainedSyntax;
        }
 
        /**
@@ -253,4 +259,69 @@
                        'weight' => $weight,
                ];
        }
+
+       /**
+        * @return bool
+        */
+       public function areResultsPossible() {
+               return $this->resultsPossible;
+       }
+
+       /**
+        * @param bool $isEmpty
+        */
+       public function setResultsPossible( $possible ) {
+               $this->resultsPossible = $possible;
+       }
+
+       /**
+        * @return bool
+        */
+       public function isSyntaxUsed() {
+               return count( $this->syntaxUsed ) > 0;
+       }
+
+       /**
+        * @return string[]
+        */
+       public function getSyntaxUsed() {
+               return $this->syntaxUsed;
+       }
+
+       /**
+        * @param string $feature
+        */
+       public function addSyntaxUsed( $feature ) {
+               $this->syntaxUsed[$feature] = true;
+       }
+
+       /**
+        * @return string
+        * @todo It might be possible to determine this based on the features 
used.
+        */
+       public function getSearchType() {
+               return $this->searchType;
+       }
+
+       /**
+        * @param string $type
+        */
+       public function setSearchType( $type ) {
+               $this->searchType = $type;
+       }
+
+       public function addFilter( \Elastica\AbstractFilter $filter ) {
+               $this->filters[] = $filter;
+       }
+
+       public function addNotFilter( \Elastica\AbstractFilter $filter ) {
+               $this->notFilters[] = $filter;
+       }
+
+       /**
+        * @return \Elastica\AbstractQuery|null
+        */
+       public function unifyFilters() {
+               return Filters::unify( $this->filters, $this->notFilters );
+       }
 }
diff --git a/includes/Searcher.php b/includes/Searcher.php
index 31e0f6a..f667f94 100644
--- a/includes/Searcher.php
+++ b/includes/Searcher.php
@@ -115,14 +115,6 @@
         */
        private $query = null;
        /**
-        * @var \Elastica\Query\AbstractQuery[] filters that MUST hold true of 
all results
-        */
-       private $filters = array();
-       /**
-        * @var \Elastica\Query\AbstractQuery[] filters that MUST NOT hold true 
of all results
-        */
-       private $notFilters = array();
-       /**
         * @var array
         */
        private $suggest = null;
@@ -297,12 +289,13 @@
                        $allQuery = new \Elastica\Query\MultiMatch();
                        $allQuery->setQuery( $search );
                        $allQuery->setFields( array( 'all_near_match', 
'all_near_match.asciifolding' ) );
-                       $this->filters[] = $allQuery;
+                       $this->searchContext->addFilter( $allQuery );
                } else {
-                       $this->filters[] = $this->highlightQuery;
+                       $this->searchContext->addFilter( $this->highlightQuery 
);
                }
+               $this->searchContext->setSearchType( 'near_match' );
 
-               return $this->search( 'near_match', $search );
+               return $this->search( $search );
        }
 
        /**
@@ -313,6 +306,7 @@
        public function prefixSearch( $search ) {
                $this->checkTitleSearchRequestLength( $search );
 
+               $this->searchContext->setSearchType( 'prefix' );
                if ( $search ) {
                        if ( $this->config->get( 
'CirrusSearchPrefixSearchStartsWithAnyWord' ) ) {
                                $match = new \Elastica\Query\Match();
@@ -321,7 +315,7 @@
                                        'analyzer' => 'plain',
                                        'operator' => 'and',
                                ) );
-                               $this->filters[] = $match;
+                               $this->searchContext->addFilter( $match );
                        } else {
                                // Elasticsearch seems to have trouble 
extracting the proper terms to highlight
                                // from the default query we make so we feed it 
exactly the right query to highlight.
@@ -342,7 +336,7 @@
                /** @suppress PhanDeprecatedFunction */
                $this->searchContext->setBoostLinks( true );
 
-               return $this->search( 'prefix', $search );
+               return $this->search( $search );
        }
 
        /**
@@ -366,16 +360,15 @@
 
                // Transform Mediawiki specific syntax to filters and extra 
(pre-escaped) query string
                $originalTerm = $term;
-               $searchContainedSyntax = false;
                $this->term = $term;
-               $searchType = 'full_text';
+               $this->searchContext->setSearchType( 'full_text' );
                // Handle title prefix notation
                $prefixPos = strpos( $this->term, 'prefix:' );
                if ( $prefixPos !== false ) {
                        $value = substr( $this->term, 7 + $prefixPos );
                        $value = trim( $value, '"' ); // Trim quotes in case 
the user wanted to quote the prefix
                        if ( strlen( $value ) > 0 ) {
-                               $searchContainedSyntax = true;
+                               $this->searchContext->addSyntaxUsed( "prefix" );
                                $this->term = substr( $this->term, 0, max( 0, 
$prefixPos - 1 ) );
                                $this->suggestSuffixes[] = ' prefix:' . $value;
                                // Suck namespaces out of $value
@@ -388,20 +381,19 @@
                                        $value = str_replace( '_', ' ', $value 
);
                                        $prefixQuery = new 
\Elastica\Query\Match();
                                        $prefixQuery->setFieldQuery( 
'title.prefix', $value );
-                                       $this->filters[] = $prefixQuery;
+                                       $this->searchContext->addFilter( 
$prefixQuery );
                                }
                        }
                }
 
-               $preferRecentDecayPortion = $this->config->get( 
'CirrusSearchPreferRecentDefaultDecayPortion' );
-               $preferRecentHalfLife = $this->config->get( 
'CirrusSearchPreferRecentDefaultHalfLife' );
-               $unspecifiedDecayPortion = $this->config->get( 
'CirrusSearchPreferRecentUnspecifiedDecayPortion' );
                // Matches "prefer-recent:" and then an optional floating point 
number <= 1 but >= 0 (decay
                // portion) and then an optional comma followed by another 
floating point number >= 0 (half life)
                $this->extractSpecialSyntaxFromTerm(
                        '/prefer-recent:(1|0?(?:\.\d+)?)?(?:,(\d*\.?\d+))? ?/',
-                       function ( $matches ) use ( $unspecifiedDecayPortion, 
&$preferRecentDecayPortion, &$preferRecentHalfLife,
-                                       &$searchContainedSyntax ) {
+                       function ( $matches ) {
+                               $preferRecentDecayPortion = $this->config->get( 
'CirrusSearchPreferRecentDefaultDecayPortion' );
+                               $preferRecentHalfLife = $this->config->get( 
'CirrusSearchPreferRecentDefaultHalfLife' );
+                               $unspecifiedDecayPortion = $this->config->get( 
'CirrusSearchPreferRecentUnspecifiedDecayPortion' );
                                if ( isset( $matches[ 1 ] ) && strlen( 
$matches[ 1 ] ) ) {
                                        $preferRecentDecayPortion = floatval( 
$matches[ 1 ] );
                                } else {
@@ -410,40 +402,38 @@
                                if ( isset( $matches[ 2 ] ) ) {
                                        $preferRecentHalfLife = floatval( 
$matches[ 2 ] );
                                }
-                               $searchContainedSyntax = true;
+                               $this->searchContext->setPreferRecentOptions( 
$preferRecentDecayPortion, $preferRecentHalfLife );
+                               $this->searchContext->addSyntaxUsed( 
'prefer-recent' );
                                return '';
                        }
                );
-               $this->searchContext->setPreferRecentOptions( 
$preferRecentDecayPortion, $preferRecentHalfLife );
 
                $this->extractSpecialSyntaxFromTerm(
                        '/^\s*local:/',
                        function () {
                                $this->limitSearchToLocalWiki( true );
+                               $this->addSyntaxUsed( 'local' );
                                return '';
                        }
                );
 
                // Handle other filters
-               $filters = $this->filters;
-               $notFilters = $this->notFilters;
-               $highlightSource = array();
                $this->extractSpecialSyntaxFromTerm(
                        
'/(?<not>-)?insource:\/(?<pattern>(?:[^\\\\\/]|\\\\.)+)\/(?<insensitive>i)? ?/',
-                       function ( $matches ) use ( &$filters, &$notFilters, 
&$searchContainedSyntax, &$searchType, &$highlightSource ) {
+                       function ( $matches ) {
 
                                if ( !$this->config->get( 
'CirrusSearchEnableRegex' ) ) {
                                        return;
                                }
 
-                               $searchContainedSyntax = true;
-                               $searchType = 'regex';
+                               $this->searchContext->addSyntaxUsed( 'regex' );
+                               $this->searchContext->setSearchType( 'regex' );
                                $insensitive = !empty( $matches[ 'insensitive' 
] );
 
-                               $filterDestination = &$filters;
                                if ( !empty( $matches[ 'not' ] ) ) {
-                                       $filterDestination = &$notFilters;
+                                       $negated = true;
                                } else {
+                                       $negated = false;
                                        $highlightSource[] = array(
                                                'pattern' => $matches[ 
'pattern' ],
                                                'locale' => $this->config->get( 
'LanguageCode' ),
@@ -467,7 +457,6 @@
                                        }
                                        $filter->setCaseSensitive( 
!$insensitive );
                                        $filter->setLocale( $this->config->get( 
'LanguageCode' ) );
-                                       $filterDestination[] = $filter;
                                } else {
                                        // Without the extra plugin we need to 
use groovy to attempt the regex.
                                        // Its less good but its something.
@@ -492,7 +481,7 @@
 }
 
 GROOVY;
-                                       $filterDestination[] = new 
\Elastica\Query\Script( new \Elastica\Script\Script(
+                                       $filter = new \Elastica\Query\Script( 
new \Elastica\Script\Script(
                                                $script,
                                                array(
                                                        'pattern' => '.*(' . 
$matches[ 'pattern' ] . ').*',
@@ -506,75 +495,72 @@
                                                'groovy'
                                        ) );
                                }
+
+                               if ( $negated ) {
+                                       $this->searchContext->addNotFilter( 
$filter );
+                               } else {
+                                       $this->searchContext->addFilter( 
$filter );
                        }
                );
                // Match filters that look like foobar:thing or foobar:"thing 
thing"
                // The {7,16} keeps this from having horrible performance on 
big strings
-               $fuzzyQuery = $this->fuzzyQuery;
-               $isEmptyQuery = false;
                $this->extractSpecialSyntaxFromTerm(
                        
'/(?<key>[a-z\\-]{7,16}):\s*(?<value>"(?<quoted>(?:[^"]|(?<=\\\)")+)"|(?<unquoted>\S+))
 ?/',
-                       function ( $matches ) use ( &$filters, &$notFilters, 
&$searchType,
-                                       &$searchContainedSyntax, &$fuzzyQuery, 
&$highlightSource, &$isEmptyQuery ) {
+                       function ( $matches ) {
                                $key = $matches['key'];
                                $quotedValue = $matches['value'];
                                $value = $matches['quoted'] !== ''
                                        ? str_replace( '\"', '"', 
$matches['quoted'] )
                                        : $matches['unquoted'];
-                               $filterDestination = &$filters;
-                               $keepText = true;
-                               $negated = false;
                                if ( $key[ 0 ] === '-' ) {
                                        $negated = true;
                                        $key = substr( $key, 1 );
-                                       $filterDestination = &$notFilters;
-                                       $keepText = false;
+                               } else {
+                                       $negated = false;
                                }
+                               $keepText = false;
+                               $filter = null;
                                switch ( $key ) {
                                        case 'nearcoord':
                                                list( $coord, $radius ) = 
Util::parseGeoNearby( $value );
                                                if ( $coord ) {
-                                                       $searchType = 'geo_' . 
$searchType;
-                                                       $filterDestination[] = 
Filters::geo( $coord, $radius );
-                                                       $searchContainedSyntax 
= true;
-                                                       return '';
+                                                       
$this->searchContext->setSearchType( 'geo_' . 
$this->searchContext->getSearchType() );
+                                                       $filter = Filters::geo( 
$coord, $radius );
+                                                       
$this->searchContext->addSyntaxUsed( 'geo' );
                                                }
-                                               return $matches[0];
+                                               break;
                                        case 'boost-nearcoord':
                                                // @todo Do we need a slightly 
different syntax for user specified weights?
                                                list( $coord, $radius ) = 
Util::parseGeoNearby( $value );
                                                if ( $coord ) {
-                                                       $searchType = 'geo_' . 
$searchType;
+                                                       
$this->searchContext->setSearchType( 'geo_' . 
$this->searchContext->getSearchType() );
                                                        
$this->getSearchContext()
                                                                ->addGeoBoost( 
$coord, $radius, $negated ? 0.1 : 1 );
-                                                       $searchContainedSyntax 
= true;
-                                                       return '';
+                                                       
$this->searchContext->addSyntaxUsed( $key );
                                                }
-                                               return $matches[0];
+                                               break;
                                        case 'neartitle':
                                                list( $coord, $radius, $exclude 
) = Util::parseGeoNearbyTitle( $value );
                                                if ( $coord ) {
-                                                       $searchType = 'geo_' . 
$searchType;
-                                                       $filterDestination[] = 
Filters::geo( $coord, $radius, $exclude );
-                                                       $searchContainedSyntax 
= true;
-                                                       return '';
+                                                       
$this->searchContext->setSearchType( 'geo_' . 
$this->searchContext->getSearchType() );
+                                                       $filter = Filters::geo( 
$coord, $radius, $exclude );
+                                                       
$this->searchContext->addSyntaxUsed( $key );
                                                }
-                                               return $matches[0];
+                                               break;
                                        case 'boost-neartitle':
                                                list( $coord, $radius, $exclude 
) = Util::parseGeoNearbyTitle( $value );
                                                if ( $coord ) {
-                                                       $searchType = 'geo_' . 
$searchType;
+                                                       
$this->searchContext->setSearchType( 'geo_' . 
$this->searchContext->getSearchType() );
                                                        
$this->getSearchContext()
                                                                ->addGeoBoost( 
$coord, $radius, $negated ? 0.1 : 1 );
-                                                       $searchContainedSyntax 
= true;
-                                                       return '';
+                                                       
$this->searchContext->addSyntaxUsed( $key );
                                                }
-                                               return $matches[0];
+                                               break;
                                        case 'boost-templates':
                                                $boostTemplates = 
Util::parseBoostTemplates( $value );
                                                
$this->getSearchContext()->setBoostTemplatesFromQuery( $boostTemplates );
-                                               $searchContainedSyntax = true;
-                                               return '';
+                                               
$this->searchContext->addSyntaxUsed( $key );
+                                               break;
                                        case 'hastemplate':
                                                // We emulate template syntax 
here as best as possible,
                                                // so things in NS_MAIN are 
prefixed with ":" and things
@@ -590,44 +576,51 @@
                                                                        
$title->getDBkey() )->getPrefixedText();
                                                        }
                                                }
-                                               $filterDestination[] = 
$this->matchPage( 'template', $value );
-                                               $searchContainedSyntax = true;
-                                               return '';
+                                               $filter = $this->matchPage( 
'template', $value );
+                                               
$this->searchContext->addSyntaxUsed( $key );
+                                               break;
                                        case 'linksto':
-                                               $filterDestination[] = 
$this->matchPage( 'outgoing_link', $value, true );
-                                               $searchContainedSyntax = true;
-                                               return '';
+                                               $filter = $this->matchPage( 
'outgoing_link', $value, true );
+                                               
$this->searchContext->addSyntaxUsed( $key );
+                                               break;
                                        case 'incategory':
                                                $categories = array_slice( 
explode( '|', $value ), 0, $this->config->get( 
'CirrusSearchMaxIncategoryOptions' ) );
-                                               $categoryFilters = 
$this->matchPageCategories( $categories );
-                                               if ( $categoryFilters === null 
) {
-                                                       $isEmptyQuery = true;
-                                               } else {
-                                                       $filterDestination[] = 
$categoryFilters;
+                                               $filter = 
$this->matchPageCategories( $categories );
+                                               if ( $filter === null ) {
+                                                       
$this->searchContext->setResultsPossible( false );
                                                }
-                                               $searchContainedSyntax = true;
-                                               return '';
+                                               
$this->searchContext->addSyntaxUsed( $key );
+                                               break;
                                        case 'insource':
-                                               $updateReferences = 
Filters::insource( $this->escaper, $this->getSearchContext(), $quotedValue );
-                                               $updateReferences( $fuzzyQuery, 
$filterDestination, $highlightSource, $searchContainedSyntax );
-                                               return '';
+                                               $updateReferences = 
Filters::insource( $this->escaper, $quotedValue );
+                                               $updateReferences( 
$this->fuzzyQuery, $filterDestination, $this->highlightSource );
+                                               
$this->searchContext->addSyntaxUsed( $key );
+                                               break;
                                        case 'intitle':
-                                               $updateReferences = 
Filters::intitle( $this->escaper, $this->getSearchContext(), $quotedValue );
-                                               $updateReferences( $fuzzyQuery, 
$filterDestination, $highlightSource, $searchContainedSyntax );
-                                               return $keepText ? 
"$quotedValue " : '';
+                                               $updateReferences = 
Filters::intitle( $this->escaper, $quotedValue );
+                                               $updateReferences( 
$this->fuzzyQuery, $filterDestination, $this->highlightSource );
+                                               
$this->searchContext->addSyntaxUsed( $key );
+                                               $keepText = !$negated;
+                                               break;
                                        default:
                                                return $matches[0];
                                }
+
+                               if ( $filter ) {
+                                       if ( $negated ) {
+                                               
$this->searchContext->addNotFilter( $filter );
+                                       } else {
+                                               
$this->searchContext->addFilter( $filter );
+                                       }
+                               }
+
+                               return $keepText ? "$quotedValue " : '';
                        }
                );
-               if ( $isEmptyQuery ) {
+
+               if ( !$this->searchContext->areResultsPossible() ) {
                        return Status::newGood( new SearchResultSet( true ) );
                }
-               $this->filters = $filters;
-               $this->notFilters = $notFilters;
-               $this->searchContext->setSearchContainedSyntax( 
$searchContainedSyntax );
-               $this->fuzzyQuery = $fuzzyQuery;
-               $this->highlightSource = $highlightSource;
 
                $this->term = $this->escaper->escapeQuotes( $this->term );
                $this->term = trim( $this->term );
@@ -775,7 +768,7 @@
                                );
                        }
 
-                       $result = $this->search( $searchType, $originalTerm );
+                       $result = $this->search( $originalTerm );
 
                        if ( !$result->isOK() && $this->isParseError( $result ) 
) {
                                // Elasticsearch has reported a parse error and 
we've already logged it when we built the status
@@ -786,13 +779,14 @@
                                        'default_operator' => 'AND',
                                ) ) );
                                $this->rescore = array(); // Not worth trying 
in this state.
-                               $result = $this->search( 'degraded_full_text', 
$originalTerm );
+                               $this->searchContext->setSearchType( 
'degraded_full_text' );
+                               $result = $this->search( $originalTerm );
                                // If that doesn't work we're out of luck but 
it should.  There no guarantee it'll work properly
                                // with the syntax we've built above but it'll 
do _something_ and we'll still work on fixing all
                                // the parse errors that come in.
                        }
                } else {
-                       $result = $this->search( $searchType, $originalTerm );
+                       $result = $this->search( $originalTerm );
                        // No need to check for a parse error here because we 
don't actually create a query for
                        // Elasticsearch to parse
                }
@@ -884,7 +878,9 @@
                        $this->connection = Connection::getPool( $this->config, 
$cluster );
                }
 
-               $this->searchContext->setSearchContainedSyntax( true );
+               $this->searchContext->addSyntaxUsed( 'more_like' );
+               $this->searchContext->setSearchType( 'more_like' );
+
                $moreLikeThisFields = $this->config->get( 
'CirrusSearchMoreLikeThisFields' );
                $moreLikeThisUseFields = $this->config->get( 
'CirrusSearchMoreLikeThisUseFields' );
                sort( $moreLikeThisFields );
@@ -922,7 +918,7 @@
                $this->query->setLike( $likeDocs );
 
                if ( $options & Searcher::MORE_LIKE_THESE_ONLY_WIKIBASE ) {
-                       $this->filters[] = new \Elastica\Query\Exists( 
'wikibase_item' );
+                       $this->searchContext->addFilter( new 
\Elastica\Query\Exists( 'wikibase_item' ) );
                }
 
                // highlight snippets are not great so it's worth running a 
match all query
@@ -930,7 +926,6 @@
                $this->highlightQuery = new \Elastica\Query\MatchAll();
 
                return $this->search(
-                       'more_like',
                        implode( ', ', $titles ),
                        $this->config->get( 'CirrusSearchMoreLikeThisTTL' )
                );
@@ -1087,12 +1082,11 @@
        /**
         * Powers full-text-like searches including prefix search.
         *
-        * @param string $type
         * @param string $for
         * @param int $cacheTTL Cache results into ObjectCache for $cacheTTL 
seconds
         * @return Status results from the query transformed by the resultsType
         */
-       private function search( $type, $for, $cacheTTL = 0 ) {
+       private function search( $for, $cacheTTL = 0 ) {
                if ( $this->limit <= 0 && ! $this->returnQuery ) {
                        if ( $this->returnResult ) {
                                return Status::newGood( array(
@@ -1134,12 +1128,12 @@
                if ( $namespaces ) {
                        $extraIndexes = $this->getAndFilterExtraIndexes();
                        if ( $this->needNsFilter( $extraIndexes, $indexType ) ) 
{
-                               $this->filters[] = new \Elastica\Query\Terms( 
'namespace', $namespaces );
+                               $this->searchContext->addFilter( new 
\Elastica\Query\Terms( 'namespace', $namespaces ) );
                        }
                }
 
                // Wrap $this->query in a filtered query if there are any 
filters
-               $unifiedFilter = Filters::unify( $this->filters, 
$this->notFilters );
+               $unifiedFilter = $this->searchContext->unifyFilters();
                if ( $unifiedFilter !== null ) {
                        if ( $this->query instanceof \Elastica\Query\BoolQuery 
) {
                                $bool = $this->query;
@@ -1153,7 +1147,7 @@
 
                // Call installBoosts right after we're done munging the query 
to include filters
                // so any rescores installBoosts adds to the query are done 
against filtered results.
-               $this->installBoosts( $type );
+               $this->installBoosts();
 
                $query->setQuery( $this->query );
 
@@ -1220,7 +1214,7 @@
                        $query->setParam( 'rescore', $modifiedRescore );
                }
 
-               $query->addParam( 'stats', $type );
+               $query->addParam( 'stats', 
$this->searchContext->getSearchType() );
                switch ( $this->sort ) {
                case 'relevance':
                        break;  // The default
@@ -1254,7 +1248,7 @@
                        $queryOptions[ 'search_type' ] = 'dfs_query_then_fetch';
                }
 
-               switch( $type ) {
+               switch( $this->searchContext->getSearchType() ) {
                case 'regex':
                        $poolCounterType = 'CirrusSearch-Regex';
                        $queryOptions[ 'timeout' ] = $this->config->getElement( 
'CirrusSearchSearchShardTimeout', 'regex' );
@@ -1278,7 +1272,7 @@
 
                $description = "{queryType} search for '{query}'";
                $logContext = array(
-                       'queryType' => $type,
+                       'queryType' => $this->searchContext->getSearchType(),
                        'query' => $for,
                        'limit' => $this->limit ?: null,
                        // null means not requested, '' means not found. If 
found
@@ -1315,6 +1309,7 @@
                                serialize( $this->resultsType )
                        ) );
                        $cacheResult = $cache->get( $key );
+                       $type = $this->searchContext->getSearchType();
                        if ( $cacheResult ) {
                                
$requestStats->increment("CirrusSearch.query_cache.$type.hit");
                                $this->successViaCache( $description, 
$logContext );
@@ -1336,7 +1331,7 @@
                                        return $this->failure( $e );
                                }
                        },
-                       function( $error, $key, $userName ) use ( $type, 
$description, $logContext ) {
+                       function( $error, $key, $userName ) use ( $description, 
$logContext ) {
                                $forUserName = $userName ? "for {userName} " : 
'';
                                LoggerFactory::getInstance( 'CirrusSearch' 
)->warning(
                                        /** @suppress PhanTypeMismatchArgument 
phan doesn't understand array addition */
@@ -1353,7 +1348,7 @@
                                                $loggedIn = 
$this->user->isLoggedIn() ? 'logged-in' : 'anonymous';
                                                return Status::newFatal( 
"cirrussearch-too-busy-for-you-{$loggedIn}-error" );
                                        }
-                                       if ( $type === 'regex' ) {
+                                       if ( 
$this->searchContext->getSearchType() === 'regex' ) {
                                                return Status::newFatal( 
'cirrussearch-regex-too-busy-error' );
                                        }
                                        return Status::newFatal( 
'cirrussearch-too-busy-error' );
@@ -1372,7 +1367,7 @@
                        }
 
                        $result->setResult( true, 
$this->resultsType->transformElasticsearchResult( $this->suggestPrefixes,
-                               $this->suggestSuffixes, $result->getValue(), 
$this->searchContext->isSearchContainedSyntax() ) );
+                               $this->suggestSuffixes, $result->getValue(), 
$this->searchContext->isSyntaxUsed() ) );
                        $isPartialResult = false;
                        if ( isset( $responseData['timed_out'] ) && 
$responseData[ 'timed_out' ] ) {
                                $isPartialResult = true;
@@ -1388,6 +1383,7 @@
                        }
 
                        if ( $cacheTTL > 0 && !$isPartialResult ) {
+                               /** @suppress PhanUndeclaredVariable */
                                
$requestStats->increment("CirrusSearch.query_cache.$type.set");
                                /** @suppress PhanUndeclaredVariable */
                                $cache->set( $key, $result, $cacheTTL );
@@ -1634,18 +1630,17 @@
                }
                $extraIndexes = OtherIndexes::getExtraIndexesForNamespaces( 
$this->getNamespaces() );
                if ( $extraIndexes ) {
-                       $this->notFilters[] = new \Elastica\Query\Term(
-                               array( 'local_sites_with_dupe' => 
$this->indexBaseName ) );
+                       $this->searchContext->addNotFilter( new 
\Elastica\Query\Term(
+                               array( 'local_sites_with_dupe' => 
$this->indexBaseName )
+                       ) );
                }
                return $extraIndexes;
        }
 
        /**
         * If there is any boosting to be done munge the the current query to 
get it right.
-        *
-        * @param string $type
         */
-       private function installBoosts( $type ) {
+       private function installBoosts() {
                if ( $this->sort !== 'relevance' ) {
                        // Boosts are irrelevant if you aren't sorting by, 
well, relevance
                        return;

-- 
To view, visit https://gerrit.wikimedia.org/r/298111
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie7a647163c4a9e0c6b61d461084cee31fe5d567e
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/CirrusSearch
Gerrit-Branch: master
Gerrit-Owner: EBernhardson <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to