From dd21f34c054f3c6daefac505474939950c6e5c07 Mon Sep 17 00:00:00 2001 From: Chad Horohoe Date: Wed, 31 Jul 2013 11:33:57 -0700 Subject: [PATCH] Select search backend by query parameter 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 | 9 ++++++++ includes/api/ApiQuerySearch.php | 36 ++++++++++++++++++++++++++--- includes/search/SearchEngine.php | 26 ++++++++++++++++++--- includes/specials/SpecialSearch.php | 8 ++++++- 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index dde97620af..0266659f3b 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -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 */ diff --git a/includes/api/ApiQuerySearch.php b/includes/api/ApiQuerySearch.php index 034983026f..36b559794a 100644 --- a/includes/api/ApiQuerySearch.php +++ b/includes/api/ApiQuerySearch.php @@ -31,6 +31,14 @@ */ 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() { diff --git a/includes/search/SearchEngine.php b/includes/search/SearchEngine.php index 4f4e31d277..bfe7dda4ce 100644 --- a/includes/search/SearchEngine.php +++ b/includes/search/SearchEngine.php @@ -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. diff --git a/includes/specials/SpecialSearch.php b/includes/specials/SpecialSearch.php index 41828464e7..4634c4f1cb 100644 --- a/includes/specials/SpecialSearch.php +++ b/includes/specials/SpecialSearch.php @@ -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; } -- 2.20.1