MediaWiki  master
ApiParamInfo.php
Go to the documentation of this file.
1 <?php
24 
28 class 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  $paths = [];
171  $manager = $module->getModuleManager();
172  if ( $manager ) {
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' => [
410  ApiBase::PARAM_ISMULTI => true,
411  ],
412  'helpformat' => [
413  ApiBase::PARAM_DFLT => 'none',
414  ApiBase::PARAM_TYPE => [ 'html', 'wikitext', 'raw', 'none' ],
415  ],
416 
417  'querymodules' => [
419  ApiBase::PARAM_ISMULTI => true,
420  ApiBase::PARAM_TYPE => $querymodules,
421  ],
422  'mainmodule' => [
424  ],
425  'pagesetmodule' => [
427  ],
428  'formatmodules' => [
430  ApiBase::PARAM_ISMULTI => true,
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 }
ApiParamInfo\getModuleInfo
getModuleInfo( $module)
Definition: ApiParamInfo.php:242
ApiUsageException\getStatusValue
getStatusValue()
Fetch the error status.
Definition: ApiUsageException.php:107
ApiParamInfo
Definition: ApiParamInfo.php:28
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:47
ApiUsageException
Exception used to abort API execution with an error.
Definition: ApiUsageException.php:29
ApiParamInfo\$helpFormat
$helpFormat
Definition: ApiParamInfo.php:30
ApiBase\addWarning
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition: ApiBase.php:1301
ApiParamInfo\listAllSubmodules
listAllSubmodules(ApiBase $module, $recursive)
List all submodules of a module.
Definition: ApiParamInfo.php:169
ApiBase\PARAM_TYPE
const PARAM_TYPE
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:71
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:565
ApiParamInfo\__construct
__construct(ApiMain $main, $action)
Definition: ApiParamInfo.php:35
ApiParamInfo\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiParamInfo.php:400
SpecialPage\getTitleFor
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,...
Definition: SpecialPage.php:92
ApiBase\makeMessage
static makeMessage( $msg, IContextSource $context, array $params=null)
Create a Message from a string or array.
Definition: ApiBase.php:1168
$res
$res
Definition: testCompression.php:57
ApiPageSet
This class contains a list of pages that the client has requested.
Definition: ApiPageSet.php:42
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:52
ApiBase\getModuleFromPath
getModuleFromPath( $path)
Get a module from its module path.
Definition: ApiBase.php:527
ContextSource\getLanguage
getLanguage()
Definition: ContextSource.php:140
RequestContext\setUser
setUser(User $user)
Definition: RequestContext.php:271
ApiBase\PARAM_DEPRECATED
const PARAM_DEPRECATED
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:76
$modules
$modules
Definition: HTMLFormElement.php:15
ApiParamInfo\execute
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiParamInfo.php:39
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:717
RequestContext
Group all the pieces relevant to the context of a request into one instance @newable.
Definition: RequestContext.php:38
ApiParamInfo\$context
RequestContext $context
Definition: ApiParamInfo.php:33
ApiResult\setIndexedTagName
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
Definition: ApiResult.php:604
ApiBase\GET_VALUES_FOR_HELP
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When set, the result could take longer to generate, but should be more thoro...
Definition: ApiBase.php:178
ApiParamInfo\isReadMode
isReadMode()
Indicates whether this module requires read rights Stable to override.
Definition: ApiParamInfo.php:396
ApiBase\PARAM_HELP_MSG_INFO
const PARAM_HELP_MSG_INFO
(array) Specify additional information tags for the parameter.
Definition: ApiBase.php:124
ApiParamInfo\formatHelpMessages
formatHelpMessages(array &$res, $key, array $msgs, $joinLists=false)
Definition: ApiParamInfo.php:192
ApiBase\PARAM_TEMPLATE_VARS
const PARAM_TEMPLATE_VARS
(array) Indicate that this is a templated parameter, and specify replacements.
Definition: ApiBase.php:158
Parser\stripOuterParagraph
static stripOuterParagraph( $html)
Strip outer.
Definition: Parser.php:6263
ApiBase\getModuleManager
getModuleManager()
Get the module manager, or null if this module has no sub-modules.
Definition: ApiBase.php:252
$path
$path
Definition: NoLocalSettings.php:25
ApiBase\PARAM_DFLT
const PARAM_DFLT
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:69
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:444
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:70
ApiParamInfo\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiParamInfo.php:436
ApiBase\getMain
getMain()
Get the main module.
Definition: ApiBase.php:460
ApiHelpParamValueMessage
Message subclass that prepends wikitext for API help.
Definition: ApiHelpParamValueMessage.php:34
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:55
ApiResult\setSubelementsList
static setSubelementsList(array &$arr, $names)
Causes the elements with the specified names to be output as subelements rather than attributes.
Definition: ApiResult.php:553
MediaWiki\ExtensionInfo
Definition: ExtensionInfo.php:8
ApiParamInfo\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiParamInfo.php:445