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 LogicException(
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  $alternatives[0] ??= self::$BACKEND_NULL_PARAM;
98  $params['backend'] = [
99  ParamValidator::PARAM_DEFAULT => $this->searchEngineConfig->getSearchType(),
100  ParamValidator::PARAM_TYPE => $alternatives,
101  ];
102  // @todo: support profile selection when multiple
103  // backends are available. The solution could be to
104  // merge all possible profiles and let ApiBase
105  // subclasses do the check. Making ApiHelp and ApiSandbox
106  // comprehensive might be more difficult.
107  } else {
108  $params += $this->buildProfileApiParam();
109  }
110 
111  return $params;
112  }
113 
122  private function buildProfileApiParam() {
123  $this->checkDependenciesSet();
124 
125  $configs = $this->getSearchProfileParams();
126  $searchEngine = $this->searchEngineFactory->create();
127  $params = [];
128  foreach ( $configs as $paramName => $paramConfig ) {
129  $profiles = $searchEngine->getProfiles(
130  $paramConfig['profile-type'],
131  $this->getContext()->getUser()
132  );
133  if ( !$profiles ) {
134  continue;
135  }
136 
137  $types = [];
138  $helpMessages = [];
139  $defaultProfile = null;
140  foreach ( $profiles as $profile ) {
141  $types[] = $profile['name'];
142  if ( isset( $profile['desc-message'] ) ) {
143  $helpMessages[$profile['name']] = $profile['desc-message'];
144  }
145 
146  if ( !empty( $profile['default'] ) ) {
147  $defaultProfile = $profile['name'];
148  }
149  }
150 
151  $params[$paramName] = [
152  ParamValidator::PARAM_TYPE => $types,
153  ApiBase::PARAM_HELP_MSG => $paramConfig['help-message'],
154  ApiBase::PARAM_HELP_MSG_PER_VALUE => $helpMessages,
155  ParamValidator::PARAM_DEFAULT => $defaultProfile,
156  ];
157  }
158 
159  return $params;
160  }
161 
175  public function buildSearchEngine( array $params = null ) {
176  $this->checkDependenciesSet();
177 
178  if ( $params == null ) {
179  return $this->searchEngineFactory->create();
180  }
181 
182  $type = $params['backend'] ?? null;
183  if ( $type === self::$BACKEND_NULL_PARAM ) {
184  $type = null;
185  }
186  $searchEngine = $this->searchEngineFactory->create( $type );
187  $searchEngine->setNamespaces( $params['namespace'] );
188  $searchEngine->setLimitOffset( $params['limit'], $params['offset'] ?? 0 );
189 
190  // Initialize requested search profiles.
191  $configs = $this->getSearchProfileParams();
192  foreach ( $configs as $paramName => $paramConfig ) {
193  if ( isset( $params[$paramName] ) ) {
194  $searchEngine->setFeatureData(
195  $paramConfig['profile-type'],
196  $params[$paramName]
197  );
198  }
199  }
200  return $searchEngine;
201  }
202 
207  abstract public function getSearchProfileParams();
208 
212  abstract public function getContext();
213 }
getUser()
const NS_MAIN
Definition: Defines.php:64
getSearchProfileParams()
buildSearchEngine(array $params=null)
Build the search engine to use.
Definition: SearchApi.php:175
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, or 'string' with PARAM_ISMULTI,...
Definition: ApiBase.php:203
const LIMIT_BIG1
Fast query, standard limit.
Definition: ApiBase.php:228
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
Definition: ApiBase.php:165
const LIMIT_BIG2
Fast query, apihighlimits limit.
Definition: ApiBase.php:230
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