Select search backend by query parameter
authorChad Horohoe <chadh@wikimedia.org>
Wed, 31 Jul 2013 18:33:57 +0000 (11:33 -0700)
committerChad Horohoe <chadh@wikimedia.org>
Tue, 13 Aug 2013 00:09:01 +0000 (17:09 -0700)
This is useful when you're doing testing of multiple search
engines and you want to compare results.

Note that it doesn't do anything for the prefix search which is ok!

Change-Id: I96a08c64ac84e93b0bec2e8b08d8943b775e68d1

includes/DefaultSettings.php
includes/api/ApiQuerySearch.php
includes/search/SearchEngine.php
includes/specials/SpecialSearch.php

index dde9762..0266659 100644 (file)
@@ -1527,6 +1527,15 @@ $wgDBadminpassword = null;
  */
 $wgSearchType = null;
 
+/**
+ * Alternative search types
+ * Sometimes you want to support multiple search engines for testing. This
+ * allows users to select their search engine of choice via url parameters
+ * to Special:Search and the action=search API. If using this, there's no
+ * need to add $wgSearchType to it, that is handled automatically.
+ */
+$wgSearchTypeAlternatives = null;
+
 /**
  * Table name prefix
  */
index 0349830..36b5597 100644 (file)
  */
 class ApiQuerySearch extends ApiQueryGeneratorBase {
 
+       /**
+        * When $wgSearchType is null, $wgSearchAlternatives[0] is null. Null isn't
+        * a valid option for an array for PARAM_TYPE, so we'll use a fake name
+        * that can't possibly be a class name and describes what the null behavior
+        * does
+        */
+       const BACKEND_NULL_PARAM = 'database-backed';
+
        public function __construct( $query, $moduleName ) {
                parent::__construct( $query, $moduleName, 'sr' );
        }
@@ -59,7 +67,8 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                $prop = array_flip( $params['prop'] );
 
                // Create search engine instance and set options
-               $search = SearchEngine::create();
+               $search = isset( $params['backend'] ) && $params['backend'] != self::BACKEND_NULL_PARAM ?
+                       SearchEngine::create( $params['backend'] ) : SearchEngine::create();
                $search->setLimitOffset( $limit + 1, $params['offset'] );
                $search->setNamespaces( $params['namespace'] );
                $search->showRedirects = $params['redirects'];
@@ -201,7 +210,9 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
        }
 
        public function getAllowedParams() {
-               return array(
+               global $wgSearchType;
+
+               $params = array(
                        'search' => array(
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => true
@@ -254,10 +265,23 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                                ApiBase::PARAM_MAX2 => ApiBase::LIMIT_SML2
                        )
                );
+
+               $alternatives = SearchEngine::getSearchTypes();
+               if ( count( $alternatives ) > 1 ) {
+                       if ( $alternatives[0] === null ) {
+                               $alternatives[0] = self::BACKEND_NULL_PARAM;
+                       }
+                       $params['backend'] = array(
+                               ApiBase::PARAM_DFLT => $wgSearchType,
+                               ApiBase::PARAM_TYPE => $alternatives,
+                       );
+               }
+
+               return $params;
        }
 
        public function getParamDescription() {
-               return array(
+               $descriptions = array(
                        'search' => 'Search for all page titles (or content) that has this value',
                        'namespace' => 'The namespace(s) to enumerate',
                        'what' => 'Search inside the text or titles',
@@ -280,6 +304,12 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                        'offset' => 'Use this value to continue paging (return by query)',
                        'limit' => 'How many total pages to return'
                );
+
+               if ( count( SearchEngine::getSearchTypes() ) > 1 ) {
+                       $descriptions['backend'] = 'Which search backend to use, if not the default';
+               }
+
+               return $descriptions;
        }
 
        public function getResultProperties() {
index 4f4e31d..bfe7dda 100644 (file)
@@ -453,13 +453,17 @@ class SearchEngine {
         * Load up the appropriate search engine class for the currently
         * active database backend, and return a configured instance.
         *
+        * @param String $type Type of search backend, if not the default
         * @return SearchEngine
         */
-       public static function create() {
+       public static function create( $type = null ) {
                global $wgSearchType;
                $dbr = null;
-               if ( $wgSearchType ) {
-                       $class = $wgSearchType;
+
+               $alternatives = self::getSearchTypes();
+               $type = $type !== null ? $type : $wgSearchType;
+               if ( $type && in_array( $type, $alternatives ) ) {
+                       $class = $type;
                } else {
                        $dbr = wfGetDB( DB_SLAVE );
                        $class = $dbr->getSearchEngine();
@@ -469,6 +473,22 @@ class SearchEngine {
                return $search;
        }
 
+       /**
+        * Return the search engines we support. If only $wgSearchType
+        * is set, it'll be an array of just that one item.
+        *
+        * @return array
+        */
+       public static function getSearchTypes() {
+               global $wgSearchType, $wgSearchTypeAlternatives;
+               static $alternatives = null;
+               if ( $alternatives === null ) {
+                       $alternatives = $wgSearchTypeAlternatives ?: array();
+                       array_unshift( $alternatives, $wgSearchType );
+               }
+               return $alternatives;
+       }
+
        /**
         * Create or update the search index record for the given page.
         * Title and text should be pre-processed.
index 4182846..4634c4f 100644 (file)
@@ -42,6 +42,9 @@ class SpecialSearch extends SpecialPage {
        /// Search engine
        protected $searchEngine;
 
+       /// Search engine type, if not default
+       protected $searchEngineType;
+
        /// For links
        protected $extraParams = array();
 
@@ -98,6 +101,8 @@ class SpecialSearch extends SpecialPage {
 
                $this->load();
 
+               $this->searchEngineType = $request->getVal( 'backend' );
+
                if ( $request->getVal( 'fulltext' )
                        || !is_null( $request->getVal( 'offset' ) )
                        || !is_null( $request->getVal( 'searchx' ) ) )
@@ -1171,7 +1176,8 @@ class SpecialSearch extends SpecialPage {
         */
        public function getSearchEngine() {
                if ( $this->searchEngine === null ) {
-                       $this->searchEngine = SearchEngine::create();
+                       $this->searchEngine = $this->searchEngineType ?
+                               SearchEngine::create( $this->searchEngineType ) : SearchEngine::create();
                }
                return $this->searchEngine;
        }