]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/api/SearchApi.php
MediaWiki 1.30.2-scripts2
[autoinstalls/mediawiki.git] / includes / api / SearchApi.php
1 <?php
2 use MediaWiki\MediaWikiServices;
3
4 /**
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  * @file
21  * @since 1.28
22  */
23
24 /**
25  * Traits for API components that use a SearchEngine.
26  * @ingroup API
27  */
28 trait SearchApi {
29
30         /**
31          * When $wgSearchType is null, $wgSearchAlternatives[0] is null. Null isn't
32          * a valid option for an array for PARAM_TYPE, so we'll use a fake name
33          * that can't possibly be a class name and describes what the null behavior
34          * does
35          */
36         private static $BACKEND_NULL_PARAM = 'database-backed';
37
38         /**
39          * The set of api parameters that are shared between api calls that
40          * call the SearchEngine. Primarily this defines parameters that
41          * are utilized by self::buildSearchEngine().
42          *
43          * @param bool $isScrollable True if the api offers scrolling
44          * @return array
45          */
46         public function buildCommonApiParams( $isScrollable = true ) {
47                 $params = [
48                         'search' => [
49                                 ApiBase::PARAM_TYPE => 'string',
50                                 ApiBase::PARAM_REQUIRED => true,
51                         ],
52                         'namespace' => [
53                                 ApiBase::PARAM_DFLT => NS_MAIN,
54                                 ApiBase::PARAM_TYPE => 'namespace',
55                                 ApiBase::PARAM_ISMULTI => true,
56                         ],
57                         'limit' => [
58                                 ApiBase::PARAM_DFLT => 10,
59                                 ApiBase::PARAM_TYPE => 'limit',
60                                 ApiBase::PARAM_MIN => 1,
61                                 ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
62                                 ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2,
63                         ],
64                 ];
65                 if ( $isScrollable ) {
66                         $params['offset'] = [
67                                 ApiBase::PARAM_DFLT => 0,
68                                 ApiBase::PARAM_TYPE => 'integer',
69                                 ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
70                         ];
71                 }
72
73                 $searchConfig = MediaWikiServices::getInstance()->getSearchEngineConfig();
74                 $alternatives = $searchConfig->getSearchTypes();
75                 if ( count( $alternatives ) > 1 ) {
76                         if ( $alternatives[0] === null ) {
77                                 $alternatives[0] = self::$BACKEND_NULL_PARAM;
78                         }
79                         $this->allowedParams['backend'] = [
80                                 ApiBase::PARAM_DFLT => $searchConfig->getSearchType(),
81                                 ApiBase::PARAM_TYPE => $alternatives,
82                         ];
83                         // @todo: support profile selection when multiple
84                         // backends are available. The solution could be to
85                         // merge all possible profiles and let ApiBase
86                         // subclasses do the check. Making ApiHelp and ApiSandbox
87                         // comprehensive might be more difficult.
88                 } else {
89                         $params += $this->buildProfileApiParam();
90                 }
91
92                 return $params;
93         }
94
95         /**
96          * Build the profile api param definitions. Makes bold assumption only one search
97          * engine is available, ensure that is true before calling.
98          *
99          * @return array array containing available additional api param definitions.
100          *  Empty if profiles are not supported by the searchEngine implementation.
101          */
102         private function buildProfileApiParam() {
103                 $configs = $this->getSearchProfileParams();
104                 $searchEngine = MediaWikiServices::getInstance()->newSearchEngine();
105                 $params = [];
106                 foreach ( $configs as $paramName => $paramConfig ) {
107                         $profiles = $searchEngine->getProfiles( $paramConfig['profile-type'],
108                                 $this->getContext()->getUser() );
109                         if ( !$profiles ) {
110                                 continue;
111                         }
112
113                         $types = [];
114                         $helpMessages = [];
115                         $defaultProfile = null;
116                         foreach ( $profiles as $profile ) {
117                                 $types[] = $profile['name'];
118                                 if ( isset( $profile['desc-message'] ) ) {
119                                         $helpMessages[$profile['name']] = $profile['desc-message'];
120                                 }
121                                 if ( !empty( $profile['default'] ) ) {
122                                         $defaultProfile = $profile['name'];
123                                 }
124                         }
125
126                         $params[$paramName] = [
127                                 ApiBase::PARAM_TYPE => $types,
128                                 ApiBase::PARAM_HELP_MSG => $paramConfig['help-message'],
129                                 ApiBase::PARAM_HELP_MSG_PER_VALUE => $helpMessages,
130                                 ApiBase::PARAM_DFLT => $defaultProfile,
131                         ];
132                 }
133
134                 return $params;
135         }
136
137         /**
138          * Build the search engine to use.
139          * If $params is provided then the following searchEngine options
140          * will be set:
141          *  - backend: which search backend to use
142          *  - limit: mandatory
143          *  - offset: optional, if set limit will be incremented by
144          *    one ( to support the continue parameter )
145          *  - namespace: mandatory
146          *  - search engine profiles defined by SearchApi::getSearchProfileParams()
147          * @param string[]|null $params API request params (must be sanitized by
148          * ApiBase::extractRequestParams() before)
149          * @return SearchEngine the search engine
150          */
151         public function buildSearchEngine( array $params = null ) {
152                 if ( $params != null ) {
153                         $type = isset( $params['backend'] ) ? $params['backend'] : null;
154                         if ( $type === self::$BACKEND_NULL_PARAM ) {
155                                 $type = null;
156                         }
157                         $searchEngine = MediaWikiServices::getInstance()->getSearchEngineFactory()->create( $type );
158                         $limit = $params['limit'];
159                         $searchEngine->setNamespaces( $params['namespace'] );
160                         $offset = null;
161                         if ( isset( $params['offset'] ) ) {
162                                 // If the API supports offset then it probably
163                                 // wants to fetch limit+1 so it can check if
164                                 // more results are available to properly set
165                                 // the continue param
166                                 $offset = $params['offset'];
167                                 $limit += 1;
168                         }
169                         $searchEngine->setLimitOffset( $limit, $offset );
170
171                         // Initialize requested search profiles.
172                         $configs = $this->getSearchProfileParams();
173                         foreach ( $configs as $paramName => $paramConfig ) {
174                                 if ( isset( $params[$paramName] ) ) {
175                                         $searchEngine->setFeatureData(
176                                                 $paramConfig['profile-type'],
177                                                 $params[$paramName]
178                                         );
179                                 }
180                         }
181                 } else {
182                         $searchEngine = MediaWikiServices::getInstance()->newSearchEngine();
183                 }
184                 return $searchEngine;
185         }
186
187         /**
188          * @return array[] array of arrays mapping from parameter name to a two value map
189          *  containing 'help-message' and 'profile-type' keys.
190          */
191         abstract public function getSearchProfileParams();
192
193         /**
194          * @return IContextSource
195          */
196         abstract public function getContext();
197 }