MediaWiki  master
SearchApi.php
Go to the documentation of this file.
1 <?php
2 
25 
30 trait SearchApi {
31 
33  private $searchEngineConfig = null;
34 
36  private $searchEngineFactory = null;
37 
38  private function checkDependenciesSet() {
39  // Since this is a trait, we can't have a constructor where the services
40  // that we need are injected. Instead, the api modules that use this trait
41  // are responsible for setting them (since api modules *can* have services
42  // injected). Double check that the api module did indeed set them
43  if ( !$this->searchEngineConfig || !$this->searchEngineFactory ) {
44  throw new MWException(
45  'SearchApi requires both a SearchEngineConfig and SearchEngineFactory to be set'
46  );
47  }
48  }
49 
56  private static $BACKEND_NULL_PARAM = 'database-backed';
57 
66  public function buildCommonApiParams( $isScrollable = true ) {
67  $this->checkDependenciesSet();
68 
69  $params = [
70  'search' => [
71  ParamValidator::PARAM_TYPE => 'string',
72  ParamValidator::PARAM_REQUIRED => true,
73  ],
74  'namespace' => [
75  ParamValidator::PARAM_DEFAULT => NS_MAIN,
76  ParamValidator::PARAM_TYPE => 'namespace',
77  ParamValidator::PARAM_ISMULTI => true,
78  ],
79  'limit' => [
80  ParamValidator::PARAM_DEFAULT => 10,
81  ParamValidator::PARAM_TYPE => 'limit',
82  IntegerDef::PARAM_MIN => 1,
83  IntegerDef::PARAM_MAX => ApiBase::LIMIT_BIG1,
84  IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_BIG2,
85  ],
86  ];
87  if ( $isScrollable ) {
88  $params['offset'] = [
89  ParamValidator::PARAM_DEFAULT => 0,
90  ParamValidator::PARAM_TYPE => 'integer',
91  ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
92  ];
93  }
94 
95  $alternatives = $this->searchEngineConfig->getSearchTypes();
96  if ( count( $alternatives ) > 1 ) {
97  if ( $alternatives[0] === null ) {
98  $alternatives[0] = self::$BACKEND_NULL_PARAM;
99  }
100  $params['backend'] = [
101  ParamValidator::PARAM_DEFAULT => $this->searchEngineConfig->getSearchType(),
102  ParamValidator::PARAM_TYPE => $alternatives,
103  ];
104  // @todo: support profile selection when multiple
105  // backends are available. The solution could be to
106  // merge all possible profiles and let ApiBase
107  // subclasses do the check. Making ApiHelp and ApiSandbox
108  // comprehensive might be more difficult.
109  } else {
110  $params += $this->buildProfileApiParam();
111  }
112 
113  return $params;
114  }
115 
124  private function buildProfileApiParam() {
125  $this->checkDependenciesSet();
126 
127  $configs = $this->getSearchProfileParams();
128  $searchEngine = $this->searchEngineFactory->create();
129  $params = [];
130  foreach ( $configs as $paramName => $paramConfig ) {
131  $profiles = $searchEngine->getProfiles(
132  $paramConfig['profile-type'],
133  $this->getContext()->getUser()
134  );
135  if ( !$profiles ) {
136  continue;
137  }
138 
139  $types = [];
140  $helpMessages = [];
141  $defaultProfile = null;
142  foreach ( $profiles as $profile ) {
143  $types[] = $profile['name'];
144  if ( isset( $profile['desc-message'] ) ) {
145  $helpMessages[$profile['name']] = $profile['desc-message'];
146  }
147 
148  if ( !empty( $profile['default'] ) ) {
149  $defaultProfile = $profile['name'];
150  }
151  }
152 
153  $params[$paramName] = [
154  ParamValidator::PARAM_TYPE => $types,
155  ApiBase::PARAM_HELP_MSG => $paramConfig['help-message'],
156  ApiBase::PARAM_HELP_MSG_PER_VALUE => $helpMessages,
157  ParamValidator::PARAM_DEFAULT => $defaultProfile,
158  ];
159  }
160 
161  return $params;
162  }
163 
177  public function buildSearchEngine( array $params = null ) {
178  $this->checkDependenciesSet();
179 
180  if ( $params == null ) {
181  return $this->searchEngineFactory->create();
182  }
183 
184  $type = $params['backend'] ?? null;
185  if ( $type === self::$BACKEND_NULL_PARAM ) {
186  $type = null;
187  }
188  $searchEngine = $this->searchEngineFactory->create( $type );
189  $searchEngine->setNamespaces( $params['namespace'] );
190  $searchEngine->setLimitOffset( $params['limit'], $params['offset'] ?? 0 );
191 
192  // Initialize requested search profiles.
193  $configs = $this->getSearchProfileParams();
194  foreach ( $configs as $paramName => $paramConfig ) {
195  if ( isset( $params[$paramName] ) ) {
196  $searchEngine->setFeatureData(
197  $paramConfig['profile-type'],
198  $params[$paramName]
199  );
200  }
201  }
202  return $searchEngine;
203  }
204 
209  abstract public function getSearchProfileParams();
210 
214  abstract public function getContext();
215 }
getUser()
const NS_MAIN
Definition: Defines.php:64
getSearchProfileParams()
buildSearchEngine(array $params=null)
Build the search engine to use.
Definition: SearchApi.php:177
buildCommonApiParams( $isScrollable=true)
The set of api parameters that are shared between api calls that call the SearchEngine.
Definition: SearchApi.php:66
getContext()
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
Definition: ApiBase.php:196
const LIMIT_BIG1
Fast query, standard limit.
Definition: ApiBase.php:221
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:163
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition: ApiBase.php:223
MediaWiki exception.
Definition: MWException.php:29
Service for formatting and validating API parameters.
Type definition for integer types.
Definition: IntegerDef.php:23
trait SearchApi
Traits for API components that use a SearchEngine.
Definition: SearchApi.php:30