MediaWiki REL1_35
ApiParamInfo.php
Go to the documentation of this file.
1<?php
24
28class ApiParamInfo extends ApiBase {
29
30 private $helpFormat;
31
33 private $context;
34
35 public function __construct( ApiMain $main, $action ) {
36 parent::__construct( $main, $action );
37 }
38
39 public function execute() {
40 // Get parameters
41 $params = $this->extractRequestParams();
42
43 $this->helpFormat = $params['helpformat'];
44 $this->context = new RequestContext;
45 $this->context->setUser( new User ); // anon to avoid caching issues
46 $this->context->setLanguage( $this->getMain()->getLanguage() );
47
48 if ( is_array( $params['modules'] ) ) {
49 $modules = [];
50 foreach ( $params['modules'] as $path ) {
51 if ( $path === '*' || $path === '**' ) {
52 $path = "main+$path";
53 }
54 if ( substr( $path, -2 ) === '+*' || substr( $path, -2 ) === ' *' ) {
55 $submodules = true;
56 $path = substr( $path, 0, -2 );
57 $recursive = false;
58 } elseif ( substr( $path, -3 ) === '+**' || substr( $path, -3 ) === ' **' ) {
59 $submodules = true;
60 $path = substr( $path, 0, -3 );
61 $recursive = true;
62 } else {
63 $submodules = false;
64 }
65
66 if ( $submodules ) {
67 try {
68 $module = $this->getModuleFromPath( $path );
69 } catch ( ApiUsageException $ex ) {
70 foreach ( $ex->getStatusValue()->getErrors() as $error ) {
71 $this->addWarning( $error );
72 }
73 continue;
74 }
75 $submodules = $this->listAllSubmodules( $module, $recursive );
76 if ( $submodules ) {
77 $modules = array_merge( $modules, $submodules );
78 } else {
79 $this->addWarning( [ 'apierror-badmodule-nosubmodules', $path ], 'badmodule' );
80 }
81 } else {
82 $modules[] = $path;
83 }
84 }
85 } else {
86 $modules = [];
87 }
88
89 if ( is_array( $params['querymodules'] ) ) {
90 $queryModules = $params['querymodules'];
91 foreach ( $queryModules as $m ) {
92 $modules[] = 'query+' . $m;
93 }
94 } else {
95 $queryModules = [];
96 }
97
98 if ( is_array( $params['formatmodules'] ) ) {
99 $formatModules = $params['formatmodules'];
100 foreach ( $formatModules as $m ) {
101 $modules[] = $m;
102 }
103 } else {
104 $formatModules = [];
105 }
106
107 $modules = array_unique( $modules );
108
109 $res = [];
110
111 foreach ( $modules as $m ) {
112 try {
113 $module = $this->getModuleFromPath( $m );
114 } catch ( ApiUsageException $ex ) {
115 foreach ( $ex->getStatusValue()->getErrors() as $error ) {
116 $this->addWarning( $error );
117 }
118 continue;
119 }
120 $key = 'modules';
121
122 // Back compat
123 $isBCQuery = false;
124 if ( $module->getParent() && $module->getParent()->getModuleName() == 'query' &&
125 in_array( $module->getModuleName(), $queryModules )
126 ) {
127 $isBCQuery = true;
128 $key = 'querymodules';
129 }
130 if ( in_array( $module->getModuleName(), $formatModules ) ) {
131 $key = 'formatmodules';
132 }
133
134 $item = $this->getModuleInfo( $module );
135 if ( $isBCQuery ) {
136 $item['querytype'] = $item['group'];
137 }
138 $res[$key][] = $item;
139 }
140
141 $result = $this->getResult();
142 $result->addValue( [ $this->getModuleName() ], 'helpformat', $this->helpFormat );
143
144 foreach ( $res as $key => $stuff ) {
145 ApiResult::setIndexedTagName( $res[$key], 'module' );
146 }
147
148 if ( $params['mainmodule'] ) {
149 $res['mainmodule'] = $this->getModuleInfo( $this->getMain() );
150 }
151
152 if ( $params['pagesetmodule'] ) {
153 $pageSet = new ApiPageSet( $this->getMain()->getModuleManager()->getModule( 'query' ) );
154 $res['pagesetmodule'] = $this->getModuleInfo( $pageSet );
155 unset( $res['pagesetmodule']['name'] );
156 unset( $res['pagesetmodule']['path'] );
157 unset( $res['pagesetmodule']['group'] );
158 }
159
160 $result->addValue( null, $this->getModuleName(), $res );
161 }
162
169 private function listAllSubmodules( ApiBase $module, $recursive ) {
170 $manager = $module->getModuleManager();
171 if ( $manager ) {
172 $paths = [];
173 $names = $manager->getNames();
174 sort( $names );
175 foreach ( $names as $name ) {
176 $submodule = $manager->getModule( $name );
177 $paths[] = $submodule->getModulePath();
178 if ( $recursive && $submodule->getModuleManager() ) {
179 $paths = array_merge( $paths, $this->listAllSubmodules( $submodule, $recursive ) );
180 }
181 }
182 }
183 return $paths;
184 }
185
192 protected function formatHelpMessages( array &$res, $key, array $msgs, $joinLists = false ) {
193 switch ( $this->helpFormat ) {
194 case 'none':
195 break;
196
197 case 'wikitext':
198 $ret = [];
199 foreach ( $msgs as $m ) {
200 $ret[] = $m->setContext( $this->context )->text();
201 }
202 $res[$key] = implode( "\n\n", $ret );
203 if ( $joinLists ) {
204 $res[$key] = preg_replace( '!^(([*#:;])[^\n]*)\n\n(?=\2)!m', "$1\n", $res[$key] );
205 }
206 break;
207
208 case 'html':
209 $ret = [];
210 foreach ( $msgs as $m ) {
211 $ret[] = $m->setContext( $this->context )->parseAsBlock();
212 }
213 $ret = implode( "\n", $ret );
214 if ( $joinLists ) {
215 $ret = preg_replace( '!\s*</([oud]l)>\s*<\1>\s*!', "\n", $ret );
216 }
217 $res[$key] = Parser::stripOuterParagraph( $ret );
218 break;
219
220 case 'raw':
221 $res[$key] = [];
222 foreach ( $msgs as $m ) {
223 $a = [
224 'key' => $m->getKey(),
225 'params' => $m->getParams(),
226 ];
227 ApiResult::setIndexedTagName( $a['params'], 'param' );
228 if ( $m instanceof ApiHelpParamValueMessage ) {
229 $a['forvalue'] = $m->getParamValue();
230 }
231 $res[$key][] = $a;
232 }
233 ApiResult::setIndexedTagName( $res[$key], 'msg' );
234 break;
235 }
236 }
237
242 private function getModuleInfo( $module ) {
243 $ret = [];
244 $path = $module->getModulePath();
245 $paramValidator = $module->getMain()->getParamValidator();
246
247 $ret['name'] = $module->getModuleName();
248 $ret['classname'] = get_class( $module );
249 $ret['path'] = $path;
250 if ( !$module->isMain() ) {
251 $ret['group'] = $module->getParent()->getModuleManager()->getModuleGroup(
252 $module->getModuleName()
253 );
254 }
255 $ret['prefix'] = $module->getModulePrefix();
256
257 $sourceInfo = $module->getModuleSourceInfo();
258 if ( $sourceInfo ) {
259 $ret['source'] = $sourceInfo['name'];
260 if ( isset( $sourceInfo['namemsg'] ) ) {
261 $ret['sourcename'] = $this->context->msg( $sourceInfo['namemsg'] )->text();
262 } else {
263 $ret['sourcename'] = $ret['source'];
264 }
265
266 $link = SpecialPage::getTitleFor( 'Version', 'License/' . $sourceInfo['name'] )->getFullURL();
267 if ( isset( $sourceInfo['license-name'] ) ) {
268 $ret['licensetag'] = $sourceInfo['license-name'];
269 $ret['licenselink'] = (string)$link;
270 } elseif ( ExtensionInfo::getLicenseFileNames( dirname( $sourceInfo['path'] ) ) ) {
271 $ret['licenselink'] = (string)$link;
272 }
273 }
274
275 $this->formatHelpMessages( $ret, 'description', $module->getFinalDescription() );
276
277 foreach ( $module->getHelpFlags() as $flag ) {
278 $ret[$flag] = true;
279 }
280
281 $ret['helpurls'] = (array)$module->getHelpUrls();
282 if ( isset( $ret['helpurls'][0] ) && $ret['helpurls'][0] === false ) {
283 $ret['helpurls'] = [];
284 }
285 ApiResult::setIndexedTagName( $ret['helpurls'], 'helpurl' );
286
287 if ( $this->helpFormat !== 'none' ) {
288 $ret['examples'] = [];
289 $examples = $module->getExamplesMessages();
290 foreach ( $examples as $qs => $msg ) {
291 $item = [
292 'query' => $qs
293 ];
294 $msg = ApiBase::makeMessage( $msg, $this->context, [
295 $module->getModulePrefix(),
296 $module->getModuleName(),
297 $module->getModulePath()
298 ] );
299 $this->formatHelpMessages( $item, 'description', [ $msg ] );
300 if ( isset( $item['description'] ) ) {
301 if ( is_array( $item['description'] ) ) {
302 $item['description'] = $item['description'][0];
303 } else {
304 ApiResult::setSubelementsList( $item, 'description' );
305 }
306 }
307 $ret['examples'][] = $item;
308 }
309 ApiResult::setIndexedTagName( $ret['examples'], 'example' );
310 }
311
312 $ret['parameters'] = [];
313 $ret['templatedparameters'] = [];
314 $params = $module->getFinalParams( ApiBase::GET_VALUES_FOR_HELP );
315 $paramDesc = $module->getFinalParamDescription();
316 $index = 0;
317 foreach ( $params as $name => $settings ) {
318 $settings = $paramValidator->normalizeSettings( $settings );
319
320 $item = [
321 'index' => ++$index,
322 'name' => $name,
323 ];
324
325 if ( !empty( $settings[ApiBase::PARAM_TEMPLATE_VARS] ) ) {
326 $item['templatevars'] = $settings[ApiBase::PARAM_TEMPLATE_VARS];
327 ApiResult::setIndexedTagName( $item['templatevars'], 'var' );
328 }
329
330 if ( isset( $paramDesc[$name] ) ) {
331 $this->formatHelpMessages( $item, 'description', $paramDesc[$name], true );
332 }
333
334 foreach ( $paramValidator->getParamInfo( $module, $name, $settings, [] ) as $k => $v ) {
335 $item[$k] = $v;
336 }
337
338 if ( $name === 'token' && $module->needsToken() ) {
339 $item['tokentype'] = $module->needsToken();
340 }
341
342 if ( $item['type'] === 'NULL' ) {
343 // Munge "NULL" to "string" for historical reasons
344 $item['type'] = 'string';
345 } elseif ( is_array( $item['type'] ) ) {
346 // Set indexed tag name, for historical reasons
347 ApiResult::setIndexedTagName( $item['type'], 't' );
348 }
349
350 if ( !empty( $settings[ApiBase::PARAM_HELP_MSG_INFO] ) ) {
351 $item['info'] = [];
352 foreach ( $settings[ApiBase::PARAM_HELP_MSG_INFO] as $i ) {
353 $tag = array_shift( $i );
354 $info = [
355 'name' => $tag,
356 ];
357 if ( count( $i ) ) {
358 $info['values'] = $i;
359 ApiResult::setIndexedTagName( $info['values'], 'v' );
360 }
361 $this->formatHelpMessages( $info, 'text', [
362 $this->context->msg( "apihelp-{$path}-paraminfo-{$tag}" )
363 ->numParams( count( $i ) )
364 ->params( $this->context->getLanguage()->commaList( $i ) )
365 ->params( $module->getModulePrefix() )
366 ] );
367 ApiResult::setSubelementsList( $info, 'text' );
368 $item['info'][] = $info;
369 }
370 ApiResult::setIndexedTagName( $item['info'], 'i' );
371 }
372
373 $key = empty( $settings[ApiBase::PARAM_TEMPLATE_VARS] ) ? 'parameters' : 'templatedparameters';
374 $ret[$key][] = $item;
375 }
376 ApiResult::setIndexedTagName( $ret['parameters'], 'param' );
377 ApiResult::setIndexedTagName( $ret['templatedparameters'], 'param' );
378
379 $dynamicParams = $module->dynamicParameterDocumentation();
380 if ( $dynamicParams !== null ) {
381 if ( $this->helpFormat === 'none' ) {
382 $ret['dynamicparameters'] = true;
383 } else {
384 $dynamicParams = ApiBase::makeMessage( $dynamicParams, $this->context, [
385 $module->getModulePrefix(),
386 $module->getModuleName(),
387 $module->getModulePath()
388 ] );
389 $this->formatHelpMessages( $ret, 'dynamicparameters', [ $dynamicParams ] );
390 }
391 }
392
393 return $ret;
394 }
395
396 public function isReadMode() {
397 return false;
398 }
399
400 public function getAllowedParams() {
401 // back compat
402 $querymodules = $this->getMain()->getModuleManager()
403 ->getModule( 'query' )->getModuleManager()->getNames();
404 sort( $querymodules );
405 $formatmodules = $this->getMain()->getModuleManager()->getNames( 'format' );
406 sort( $formatmodules );
407
408 return [
409 'modules' => [
411 ],
412 'helpformat' => [
413 ApiBase::PARAM_DFLT => 'none',
414 ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'raw', 'none' ],
415 ],
416
417 'querymodules' => [
420 ApiBase::PARAM_TYPE => $querymodules,
421 ],
422 'mainmodule' => [
424 ],
425 'pagesetmodule' => [
427 ],
428 'formatmodules' => [
431 ApiBase::PARAM_TYPE => $formatmodules,
432 ]
433 ];
434 }
435
436 protected function getExamplesMessages() {
437 return [
438 'action=paraminfo&modules=parse|phpfm|query%2Ballpages|query%2Bsiteinfo'
439 => 'apihelp-paraminfo-example-1',
440 'action=paraminfo&modules=query%2B*'
441 => 'apihelp-paraminfo-example-2',
442 ];
443 }
444
445 public function getHelpUrls() {
446 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Parameter_information';
447 }
448}
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:52
const PARAM_DEPRECATED
Definition ApiBase.php:98
getModuleFromPath( $path)
Get a module from its module path.
Definition ApiBase.php:582
static makeMessage( $msg, IContextSource $context, array $params=null)
Create a Message from a string or array.
Definition ApiBase.php:1223
getModuleManager()
Get the module manager, or null if this module has no sub-modules.
Definition ApiBase.php:307
getMain()
Get the main module.
Definition ApiBase.php:515
const PARAM_TYPE
Definition ApiBase.php:78
const PARAM_HELP_MSG_INFO
(array) Specify additional information tags for the parameter.
Definition ApiBase.php:179
const PARAM_DFLT
Definition ApiBase.php:70
const PARAM_TEMPLATE_VARS
(array) Indicate that this is a templated parameter, and specify replacements.
Definition ApiBase.php:213
getResult()
Get the result object.
Definition ApiBase.php:620
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:772
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition ApiBase.php:1356
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
Definition ApiBase.php:233
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:499
const PARAM_ISMULTI
Definition ApiBase.php:74
Message subclass that prepends wikitext for API help.
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:47
This class contains a list of pages that the client has requested.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
RequestContext $context
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
isReadMode()
Indicates whether this module requires read rights Stable to override.
__construct(ApiMain $main, $action)
getHelpUrls()
Return links to more detailed help pages about the module.
formatHelpMessages(array &$res, $key, array $msgs, $joinLists=false)
listAllSubmodules(ApiBase $module, $recursive)
List all submodules of a module.
getExamplesMessages()
Returns usage examples for this module.
getModuleInfo( $module)
Exception used to abort API execution with an error.
getStatusValue()
Fetch the error status.
Group all the pieces relevant to the context of a request into one instance @newable.
setUser(User $user)
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:60