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