MediaWiki master
ApiParamInfo.php
Go to the documentation of this file.
1<?php
30
34class ApiParamInfo extends ApiBase {
35
36 private $helpFormat;
37
39 private $context;
40
42 private $userFactory;
43
49 public function __construct(
50 ApiMain $main,
51 $action,
52 UserFactory $userFactory
53 ) {
54 parent::__construct( $main, $action );
55 $this->userFactory = $userFactory;
56 }
57
58 public function execute() {
59 // Get parameters
61
62 $this->helpFormat = $params['helpformat'];
63 $this->context = new RequestContext;
64 $this->context->setUser( $this->userFactory->newAnonymous() ); // anon to avoid caching issues
65 $this->context->setLanguage( $this->getMain()->getLanguage() );
66
67 if ( is_array( $params['modules'] ) ) {
68 $modules = [];
69 foreach ( $params['modules'] as $path ) {
70 if ( $path === '*' || $path === '**' ) {
71 $path = "main+$path";
72 }
73 if ( str_ends_with( $path, '+*' ) || str_ends_with( $path, ' *' ) ) {
74 $submodules = true;
75 $path = substr( $path, 0, -2 );
76 $recursive = false;
77 } elseif ( str_ends_with( $path, '+**' ) || str_ends_with( $path, ' **' ) ) {
78 $submodules = true;
79 $path = substr( $path, 0, -3 );
80 $recursive = true;
81 } else {
82 $submodules = false;
83 }
84
85 if ( $submodules ) {
86 try {
87 $module = $this->getModuleFromPath( $path );
88 } catch ( ApiUsageException $ex ) {
89 foreach ( $ex->getStatusValue()->getMessages() as $error ) {
90 $this->addWarning( $error );
91 }
92 continue;
93 }
94 // @phan-suppress-next-next-line PhanTypeMismatchArgumentNullable,PhanPossiblyUndeclaredVariable
95 // recursive is set when used
96 $submodules = $this->listAllSubmodules( $module, $recursive );
97 if ( $submodules ) {
98 $modules = array_merge( $modules, $submodules );
99 } else {
100 $this->addWarning( [ 'apierror-badmodule-nosubmodules', $path ], 'badmodule' );
101 }
102 } else {
103 $modules[] = $path;
104 }
105 }
106 } else {
107 $modules = [];
108 }
109
110 if ( is_array( $params['querymodules'] ) ) {
111 $queryModules = $params['querymodules'];
112 foreach ( $queryModules as $m ) {
113 $modules[] = 'query+' . $m;
114 }
115 } else {
116 $queryModules = [];
117 }
118
119 if ( is_array( $params['formatmodules'] ) ) {
120 $formatModules = $params['formatmodules'];
121 foreach ( $formatModules as $m ) {
122 $modules[] = $m;
123 }
124 } else {
125 $formatModules = [];
126 }
127
128 $modules = array_unique( $modules );
129
130 $res = [];
131
132 foreach ( $modules as $m ) {
133 try {
134 $module = $this->getModuleFromPath( $m );
135 } catch ( ApiUsageException $ex ) {
136 foreach ( $ex->getStatusValue()->getMessages() as $error ) {
137 $this->addWarning( $error );
138 }
139 continue;
140 }
141 $key = 'modules';
142
143 // Back compat
144 $isBCQuery = false;
145 if ( $module->getParent() && $module->getParent()->getModuleName() == 'query' &&
146 in_array( $module->getModuleName(), $queryModules )
147 ) {
148 $isBCQuery = true;
149 $key = 'querymodules';
150 }
151 if ( in_array( $module->getModuleName(), $formatModules ) ) {
152 $key = 'formatmodules';
153 }
154
155 $item = $this->getModuleInfo( $module );
156 if ( $isBCQuery ) {
157 $item['querytype'] = $item['group'];
158 }
159 $res[$key][] = $item;
160 }
161
162 $result = $this->getResult();
163 $result->addValue( [ $this->getModuleName() ], 'helpformat', $this->helpFormat );
164
165 foreach ( $res as $key => $stuff ) {
166 ApiResult::setIndexedTagName( $res[$key], 'module' );
167 }
168
169 if ( $params['mainmodule'] ) {
170 $res['mainmodule'] = $this->getModuleInfo( $this->getMain() );
171 }
172
173 if ( $params['pagesetmodule'] ) {
174 $pageSet = new ApiPageSet( $this->getMain()->getModuleManager()->getModule( 'query' ) );
175 $res['pagesetmodule'] = $this->getModuleInfo( $pageSet );
176 unset( $res['pagesetmodule']['name'] );
177 unset( $res['pagesetmodule']['path'] );
178 unset( $res['pagesetmodule']['group'] );
179 }
180
181 $result->addValue( null, $this->getModuleName(), $res );
182 }
183
190 private function listAllSubmodules( ApiBase $module, $recursive ) {
191 $paths = [];
192 $manager = $module->getModuleManager();
193 if ( $manager ) {
194 $names = $manager->getNames();
195 sort( $names );
196 foreach ( $names as $name ) {
197 $submodule = $manager->getModule( $name );
198 $paths[] = $submodule->getModulePath();
199 if ( $recursive && $submodule->getModuleManager() ) {
200 $paths = array_merge( $paths, $this->listAllSubmodules( $submodule, $recursive ) );
201 }
202 }
203 }
204 return $paths;
205 }
206
213 protected function formatHelpMessages( array &$res, $key, array $msgs, $joinLists = false ) {
214 switch ( $this->helpFormat ) {
215 case 'none':
216 break;
217
218 case 'wikitext':
219 $ret = [];
220 foreach ( $msgs as $m ) {
221 $ret[] = $m->setContext( $this->context )->text();
222 }
223 $res[$key] = implode( "\n\n", $ret );
224 if ( $joinLists ) {
225 $res[$key] = preg_replace( '!^(([*#:;])[^\n]*)\n\n(?=\2)!m', "$1\n", $res[$key] );
226 }
227 break;
228
229 case 'html':
230 $ret = [];
231 foreach ( $msgs as $m ) {
232 $ret[] = $m->setContext( $this->context )->parseAsBlock();
233 }
234 $ret = implode( "\n", $ret );
235 if ( $joinLists ) {
236 $ret = preg_replace( '!\s*</([oud]l)>\s*<\1>\s*!', "\n", $ret );
237 }
238 $res[$key] = Parser::stripOuterParagraph( $ret );
239 break;
240
241 case 'raw':
242 $res[$key] = [];
243 foreach ( $msgs as $m ) {
244 $a = [
245 'key' => $m->getKey(),
246 'params' => $m->getParams(),
247 ];
248 ApiResult::setIndexedTagName( $a['params'], 'param' );
249 if ( $m instanceof ApiHelpParamValueMessage ) {
250 $a['forvalue'] = $m->getParamValue();
251 }
252 $res[$key][] = $a;
253 }
254 ApiResult::setIndexedTagName( $res[$key], 'msg' );
255 break;
256 }
257 }
258
263 private function getModuleInfo( $module ) {
264 $ret = [];
265 $path = $module->getModulePath();
266 $paramValidator = $module->getMain()->getParamValidator();
267
268 $ret['name'] = $module->getModuleName();
269 $ret['classname'] = get_class( $module );
270 $ret['path'] = $path;
271 if ( !$module->isMain() ) {
272 $ret['group'] = $module->getParent()->getModuleManager()->getModuleGroup(
273 $module->getModuleName()
274 );
275 }
276 $ret['prefix'] = $module->getModulePrefix();
277
278 $sourceInfo = $module->getModuleSourceInfo();
279 if ( $sourceInfo ) {
280 $ret['source'] = $sourceInfo['name'];
281 if ( isset( $sourceInfo['namemsg'] ) ) {
282 $ret['sourcename'] = $this->context->msg( $sourceInfo['namemsg'] )->text();
283 } else {
284 $ret['sourcename'] = $ret['source'];
285 }
286
287 $link = SpecialPage::getTitleFor( 'Version', 'License/' . $sourceInfo['name'] )->getFullURL();
288 if ( isset( $sourceInfo['license-name'] ) ) {
289 $ret['licensetag'] = $sourceInfo['license-name'];
290 $ret['licenselink'] = (string)$link;
291 } elseif ( ExtensionInfo::getLicenseFileNames( dirname( $sourceInfo['path'] ) ) ) {
292 $ret['licenselink'] = (string)$link;
293 }
294 }
295
296 $this->formatHelpMessages( $ret, 'description', $module->getFinalDescription() );
297
298 foreach ( $module->getHelpFlags() as $flag ) {
299 $ret[$flag] = true;
300 }
301
302 $ret['helpurls'] = (array)$module->getHelpUrls();
303 if ( isset( $ret['helpurls'][0] ) && $ret['helpurls'][0] === false ) {
304 $ret['helpurls'] = [];
305 }
306 // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset False positive
307 ApiResult::setIndexedTagName( $ret['helpurls'], 'helpurl' );
308
309 if ( $this->helpFormat !== 'none' ) {
310 $ret['examples'] = [];
311 $examples = $module->getExamplesMessages();
312 foreach ( $examples as $qs => $msg ) {
313 $item = [
314 'query' => $qs
315 ];
316 $msg = ApiBase::makeMessage( $msg, $this->context, [
317 $module->getModulePrefix(),
318 $module->getModuleName(),
319 $module->getModulePath()
320 ] );
321 $this->formatHelpMessages( $item, 'description', [ $msg ] );
322 if ( isset( $item['description'] ) ) {
323 if ( is_array( $item['description'] ) ) {
324 $item['description'] = $item['description'][0];
325 } else {
326 ApiResult::setSubelementsList( $item, 'description' );
327 }
328 }
329 $ret['examples'][] = $item;
330 }
331 ApiResult::setIndexedTagName( $ret['examples'], 'example' );
332 }
333
334 $ret['parameters'] = [];
335 $ret['templatedparameters'] = [];
336 $params = $module->getFinalParams( ApiBase::GET_VALUES_FOR_HELP );
337 $paramDesc = $module->getFinalParamDescription();
338 $index = 0;
339 foreach ( $params as $name => $settings ) {
340 $settings = $paramValidator->normalizeSettings( $settings );
341
342 $item = [
343 'index' => ++$index,
344 'name' => $name,
345 ];
346
347 if ( !empty( $settings[ApiBase::PARAM_TEMPLATE_VARS] ) ) {
348 $item['templatevars'] = $settings[ApiBase::PARAM_TEMPLATE_VARS];
349 ApiResult::setIndexedTagName( $item['templatevars'], 'var' );
350 }
351
352 if ( isset( $paramDesc[$name] ) ) {
353 $this->formatHelpMessages( $item, 'description', $paramDesc[$name], true );
354 }
355
356 foreach ( $paramValidator->getParamInfo( $module, $name, $settings, [] ) as $k => $v ) {
357 $item[$k] = $v;
358 }
359
360 if ( $name === 'token' && $module->needsToken() ) {
361 $item['tokentype'] = $module->needsToken();
362 }
363
364 if ( $item['type'] === 'NULL' ) {
365 // Munge "NULL" to "string" for historical reasons
366 $item['type'] = 'string';
367 } elseif ( is_array( $item['type'] ) ) {
368 // Set indexed tag name, for historical reasons
369 ApiResult::setIndexedTagName( $item['type'], 't' );
370 }
371
372 if ( !empty( $settings[ApiBase::PARAM_HELP_MSG_INFO] ) ) {
373 $item['info'] = [];
374 foreach ( $settings[ApiBase::PARAM_HELP_MSG_INFO] as $i ) {
375 $tag = array_shift( $i );
376 $info = [
377 'name' => $tag,
378 ];
379 if ( count( $i ) ) {
380 $info['values'] = $i;
381 ApiResult::setIndexedTagName( $info['values'], 'v' );
382 }
383 $this->formatHelpMessages( $info, 'text', [
384 $this->context->msg( "apihelp-{$path}-paraminfo-{$tag}" )
385 ->numParams( count( $i ) )
386 ->params( $this->context->getLanguage()->commaList( $i ) )
387 ->params( $module->getModulePrefix() )
388 ] );
389 ApiResult::setSubelementsList( $info, 'text' );
390 $item['info'][] = $info;
391 }
392 ApiResult::setIndexedTagName( $item['info'], 'i' );
393 }
394
395 $key = empty( $settings[ApiBase::PARAM_TEMPLATE_VARS] ) ? 'parameters' : 'templatedparameters';
396 $ret[$key][] = $item;
397 }
398 ApiResult::setIndexedTagName( $ret['parameters'], 'param' );
399 ApiResult::setIndexedTagName( $ret['templatedparameters'], 'param' );
400
401 $dynamicParams = $module->dynamicParameterDocumentation();
402 if ( $dynamicParams !== null ) {
403 if ( $this->helpFormat === 'none' ) {
404 $ret['dynamicparameters'] = true;
405 } else {
406 $dynamicParams = ApiBase::makeMessage( $dynamicParams, $this->context, [
407 $module->getModulePrefix(),
408 $module->getModuleName(),
409 $module->getModulePath()
410 ] );
411 $this->formatHelpMessages( $ret, 'dynamicparameters', [ $dynamicParams ] );
412 }
413 }
414
415 return $ret;
416 }
417
418 public function isReadMode() {
419 return false;
420 }
421
422 public function getAllowedParams() {
423 // back compat
424 $querymodules = $this->getMain()->getModuleManager()
425 ->getModule( 'query' )->getModuleManager()->getNames();
426 sort( $querymodules );
427 $formatmodules = $this->getMain()->getModuleManager()->getNames( 'format' );
428 sort( $formatmodules );
429
430 return [
431 'modules' => [
432 ParamValidator::PARAM_ISMULTI => true,
433 ],
434 'helpformat' => [
435 ParamValidator::PARAM_DEFAULT => 'none',
436 ParamValidator::PARAM_TYPE => [ 'html', 'wikitext', 'raw', 'none' ],
437 ],
438
439 'querymodules' => [
440 ParamValidator::PARAM_DEPRECATED => true,
441 ParamValidator::PARAM_ISMULTI => true,
442 ParamValidator::PARAM_TYPE => $querymodules,
443 ],
444 'mainmodule' => [
445 ParamValidator::PARAM_DEPRECATED => true,
446 ],
447 'pagesetmodule' => [
448 ParamValidator::PARAM_DEPRECATED => true,
449 ],
450 'formatmodules' => [
451 ParamValidator::PARAM_DEPRECATED => true,
452 ParamValidator::PARAM_ISMULTI => true,
453 ParamValidator::PARAM_TYPE => $formatmodules,
454 ]
455 ];
456 }
457
458 protected function getExamplesMessages() {
459 return [
460 'action=paraminfo&modules=parse|phpfm|query%2Ballpages|query%2Bsiteinfo'
461 => 'apihelp-paraminfo-example-1',
462 'action=paraminfo&modules=query%2B*'
463 => 'apihelp-paraminfo-example-2',
464 ];
465 }
466
467 public function getHelpUrls() {
468 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Parameter_information';
469 }
470}
array $params
The job parameters.
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:65
getModulePrefix()
Get parameter prefix (usually two letters or an empty string).
Definition ApiBase.php:551
getModuleFromPath( $path)
Get a module from its module path.
Definition ApiBase.php:641
static makeMessage( $msg, IContextSource $context, array $params=null)
Create a Message from a string or array.
Definition ApiBase.php:1295
getParent()
Get the parent of this module.
Definition ApiBase.php:581
getHelpUrls()
Return links to more detailed help pages about the module.
Definition ApiBase.php:384
getModuleManager()
Get the module manager, or null if this module has no submodules.
Definition ApiBase.php:341
getMain()
Get the main module.
Definition ApiBase.php:560
getExamplesMessages()
Returns usage examples for this module.
Definition ApiBase.php:373
getModuleSourceInfo()
Returns information about the source of this module, if known.
Definition ApiBase.php:2133
isMain()
Returns true if this module is the main module ($this === $this->mMainModule), false otherwise.
Definition ApiBase.php:570
getFinalDescription()
Get the final module description, after hooks have had a chance to tweak it as needed.
Definition ApiBase.php:1892
const PARAM_TEMPLATE_VARS
(array) Indicate that this is a templated parameter, and specify replacements.
Definition ApiBase.php:230
getResult()
Get the result object.
Definition ApiBase.php:681
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:821
needsToken()
Returns the token type this module requires in order to execute.
Definition ApiBase.php:496
getModulePath()
Get the path to this module.
Definition ApiBase.php:621
getHelpFlags()
Generates the list of flags for the help screen and for action=paraminfo.
Definition ApiBase.php:2100
getFinalParams( $flags=0)
Get the final list of parameters, after hooks have had a chance to tweak it as needed.
Definition ApiBase.php:1921
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition ApiBase.php:1458
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:542
getFinalParamDescription()
Get final parameter descriptions, after hooks have had a chance to tweak it as needed.
Definition ApiBase.php:1952
dynamicParameterDocumentation()
Indicate if the module supports dynamically-determined parameters that cannot be included in self::ge...
Definition ApiBase.php:787
Message subclass that prepends wikitext for API help.
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:67
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...
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
isReadMode()
Indicates whether this module requires read rights.
getHelpUrls()
Return links to more detailed help pages about the module.
__construct(ApiMain $main, $action, UserFactory $userFactory)
formatHelpMessages(array &$res, $key, array $msgs, $joinLists=false)
getExamplesMessages()
Returns usage examples for this module.
static setSubelementsList(array &$arr, $names)
Causes the elements with the specified names to be output as subelements rather than attributes.
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
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.
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:158
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
Definition Parser.php:155
Parent class for all special pages.
Creates User objects.
Service for formatting and validating API parameters.