MediaWiki  master
ApiHelp.php
Go to the documentation of this file.
1 <?php
34 use Wikimedia\Parsoid\Core\TOCData;
35 use Wikimedia\RemexHtml\Serializer\SerializerNode;
36 
43 class ApiHelp extends ApiBase {
44  private SkinFactory $skinFactory;
45 
51  public function __construct(
52  ApiMain $main,
53  $action,
54  SkinFactory $skinFactory
55  ) {
56  parent::__construct( $main, $action );
57  $this->skinFactory = $skinFactory;
58  }
59 
60  public function execute() {
61  $params = $this->extractRequestParams();
62  $modules = [];
63 
64  foreach ( $params['modules'] as $path ) {
65  $modules[] = $this->getModuleFromPath( $path );
66  }
67 
68  // Get the help
69  $context = new DerivativeContext( $this->getMain()->getContext() );
70  $context->setSkin( $this->skinFactory->makeSkin( 'apioutput' ) );
71  $context->setLanguage( $this->getMain()->getLanguage() );
72  $context->setTitle( SpecialPage::getTitleFor( 'ApiHelp' ) );
73  $out = new OutputPage( $context );
74  $out->setRobotPolicy( 'noindex,nofollow' );
75  $out->setCopyrightUrl( 'https://www.mediawiki.org/wiki/Special:MyLanguage/Copyright' );
76  $out->disallowUserJs();
77  $context->setOutput( $out );
78 
79  self::getHelp( $context, $modules, $params );
80 
81  // Grab the output from the skin
82  ob_start();
83  $context->getOutput()->output();
84  $html = ob_get_clean();
85 
86  $result = $this->getResult();
87  if ( $params['wrap'] ) {
88  $data = [
89  'mime' => 'text/html',
90  'filename' => 'api-help.html',
91  'help' => $html,
92  ];
93  ApiResult::setSubelementsList( $data, 'help' );
94  $result->addValue( null, $this->getModuleName(), $data );
95  } else {
96  // Show any errors at the top of the HTML
97  $transform = [
98  'Types' => [ 'AssocAsObject' => true ],
99  'Strip' => 'all',
100  ];
101  $errors = array_filter( [
102  'errors' => $this->getResult()->getResultData( [ 'errors' ], $transform ),
103  'warnings' => $this->getResult()->getResultData( [ 'warnings' ], $transform ),
104  ] );
105  if ( $errors ) {
106  $json = FormatJson::encode( $errors, true, FormatJson::UTF8_OK );
107  // Escape any "--", some parsers might interpret that as end-of-comment.
108  // The above already escaped any "<" and ">".
109  $json = str_replace( '--', '-\u002D', $json );
110  $html = "<!-- API warnings and errors:\n$json\n-->\n$html";
111  }
112 
113  $result->reset();
114  $result->addValue( null, 'text', $html, ApiResult::NO_SIZE_CHECK );
115  $result->addValue( null, 'mime', 'text/html', ApiResult::NO_SIZE_CHECK );
116  $result->addValue( null, 'filename', 'api-help.html', ApiResult::NO_SIZE_CHECK );
117  }
118  }
119 
139  public static function getHelp( IContextSource $context, $modules, array $options ) {
140  if ( !is_array( $modules ) ) {
141  $modules = [ $modules ];
142  }
143 
144  $out = $context->getOutput();
145  $out->addModuleStyles( [
146  'mediawiki.hlist',
147  'mediawiki.apipretty',
148  ] );
149  $out->setPageTitleMsg( $context->msg( 'api-help-title' ) );
150 
151  $services = MediaWikiServices::getInstance();
152  $cache = $services->getMainWANObjectCache();
153  $cacheKey = null;
154  if ( count( $modules ) == 1 && $modules[0] instanceof ApiMain &&
155  $options['recursivesubmodules'] &&
156  $context->getLanguage()->equals( $services->getContentLanguage() )
157  ) {
158  $cacheHelpTimeout = $context->getConfig()->get( MainConfigNames::APICacheHelpTimeout );
159  if ( $cacheHelpTimeout > 0 ) {
160  // Get help text from cache if present
161  $cacheKey = $cache->makeKey( 'apihelp', $modules[0]->getModulePath(),
162  (int)!empty( $options['toc'] ),
163  str_replace( ' ', '_', SpecialVersion::getVersion( 'nodb' ) ) );
164  $cached = $cache->get( $cacheKey );
165  if ( $cached ) {
166  $out->addHTML( $cached );
167  return;
168  }
169  }
170  }
171  if ( $out->getHTML() !== '' ) {
172  // Don't save to cache, there's someone else's content in the page
173  // already
174  $cacheKey = null;
175  }
176 
177  $options['recursivesubmodules'] = !empty( $options['recursivesubmodules'] );
178  $options['submodules'] = $options['recursivesubmodules'] || !empty( $options['submodules'] );
179 
180  // Prepend lead
181  if ( empty( $options['nolead'] ) ) {
182  $msg = $context->msg( 'api-help-lead' );
183  if ( !$msg->isDisabled() ) {
184  $out->addHTML( $msg->parseAsBlock() );
185  }
186  }
187 
188  $haveModules = [];
189  $html = self::getHelpInternal( $context, $modules, $options, $haveModules );
190  if ( !empty( $options['toc'] ) && $haveModules ) {
191  $tocData = TOCData::fromLegacy( array_values( $haveModules ) );
192  $out->addHTML( Linker::generateTOC( $tocData, $context->getLanguage() ) );
193  }
194  $out->addHTML( $html );
195 
196  $helptitle = $options['helptitle'] ?? null;
197  $html = self::fixHelpLinks( $out->getHTML(), $helptitle, $haveModules );
198  $out->clearHTML();
199  $out->addHTML( $html );
200 
201  if ( $cacheKey !== null ) {
202  // @phan-suppress-next-line PhanPossiblyUndeclaredVariable $cacheHelpTimeout declared when $cacheKey is set
203  $cache->set( $cacheKey, $out->getHTML(), $cacheHelpTimeout );
204  }
205  }
206 
215  public static function fixHelpLinks( $html, $helptitle = null, $localModules = [] ) {
216  return HtmlHelper::modifyElements(
217  $html,
218  static function ( SerializerNode $node ): bool {
219  return $node->name === 'a'
220  && isset( $node->attrs['href'] )
221  && !str_contains( $node->attrs['class'] ?? '', 'apihelp-linktrail' );
222  },
223  static function ( SerializerNode $node ) use ( $helptitle, $localModules ): SerializerNode {
224  $href = $node->attrs['href'];
225  // FIXME This can't be right to do this in a loop
226  do {
227  $old = $href;
228  $href = rawurldecode( $href );
229  } while ( $old !== $href );
230  if ( preg_match( '!Special:ApiHelp/([^&/|#]+)((?:#.*)?)!', $href, $m ) ) {
231  if ( isset( $localModules[$m[1]] ) ) {
232  $href = $m[2] === '' ? '#' . $m[1] : $m[2];
233  } elseif ( $helptitle !== null ) {
234  $href = Title::newFromText( str_replace( '$1', $m[1], $helptitle ) . $m[2] )
235  ->getFullURL();
236  } else {
237  $href = wfAppendQuery( wfScript( 'api' ), [
238  'action' => 'help',
239  'modules' => $m[1],
240  ] ) . $m[2];
241  }
242  $node->attrs['href'] = $href;
243  unset( $node->attrs['title'] );
244  }
245 
246  return $node;
247  }
248  );
249  }
250 
259  private static function wrap( Message $msg, $class, $tag = 'span' ) {
260  return Html::rawElement( $tag, [ 'class' => $class ],
261  $msg->parse()
262  );
263  }
264 
274  private static function getHelpInternal( IContextSource $context, array $modules,
275  array $options, &$haveModules
276  ) {
277  $out = '';
278 
279  $level = empty( $options['headerlevel'] ) ? 2 : $options['headerlevel'];
280  if ( empty( $options['tocnumber'] ) ) {
281  $tocnumber = [ 2 => 0 ];
282  } else {
283  $tocnumber = &$options['tocnumber'];
284  }
285 
286  foreach ( $modules as $module ) {
287  $paramValidator = $module->getMain()->getParamValidator();
288  $tocnumber[$level]++;
289  $path = $module->getModulePath();
290  $module->setContext( $context );
291  $help = [
292  'header' => '',
293  'flags' => '',
294  'description' => '',
295  'help-urls' => '',
296  'parameters' => '',
297  'examples' => '',
298  'submodules' => '',
299  ];
300 
301  if ( empty( $options['noheader'] ) || !empty( $options['toc'] ) ) {
302  $anchor = $path;
303  $i = 1;
304  while ( isset( $haveModules[$anchor] ) ) {
305  $anchor = $path . '|' . ++$i;
306  }
307 
308  if ( $module->isMain() ) {
309  $headerContent = $context->msg( 'api-help-main-header' )->parse();
310  $headerAttr = [
311  'class' => 'apihelp-header',
312  ];
313  } else {
314  $name = $module->getModuleName();
315  $headerContent = htmlspecialchars(
316  $module->getParent()->getModuleManager()->getModuleGroup( $name ) . "=$name"
317  );
318  if ( $module->getModulePrefix() !== '' ) {
319  $headerContent .= ' ' .
320  $context->msg( 'parentheses', $module->getModulePrefix() )->parse();
321  }
322  // Module names are always in English and not localized,
323  // so English language and direction must be set explicitly,
324  // otherwise parentheses will get broken in RTL wikis
325  $headerAttr = [
326  'class' => [ 'apihelp-header', 'apihelp-module-name' ],
327  'dir' => 'ltr',
328  'lang' => 'en',
329  ];
330  }
331 
332  $headerAttr['id'] = $anchor;
333 
334  // T326687: Maybe transition to using a SectionMetadata object?
335  $haveModules[$anchor] = [
336  'toclevel' => count( $tocnumber ),
337  'level' => $level,
338  'anchor' => $anchor,
339  'line' => $headerContent,
340  'number' => implode( '.', $tocnumber ),
341  'index' => '',
342  ];
343  if ( empty( $options['noheader'] ) ) {
344  $help['header'] .= Html::rawElement(
345  'h' . min( 6, $level ),
346  $headerAttr,
347  $headerContent
348  );
349  }
350  } else {
351  $haveModules[$path] = true;
352  }
353 
354  $links = [];
355  $any = false;
356  for ( $m = $module; $m !== null; $m = $m->getParent() ) {
357  $name = $m->getModuleName();
358  if ( $name === 'main_int' ) {
359  $name = 'main';
360  }
361 
362  if ( count( $modules ) === 1 && $m === $modules[0] &&
363  !( !empty( $options['submodules'] ) && $m->getModuleManager() )
364  ) {
365  $link = Html::element( 'b', [ 'dir' => 'ltr', 'lang' => 'en' ], $name );
366  } else {
367  $link = SpecialPage::getTitleFor( 'ApiHelp', $m->getModulePath() )->getLocalURL();
368  $link = Html::element( 'a',
369  [ 'href' => $link, 'class' => 'apihelp-linktrail', 'dir' => 'ltr', 'lang' => 'en' ],
370  $name
371  );
372  $any = true;
373  }
374  array_unshift( $links, $link );
375  }
376  if ( $any ) {
377  $help['header'] .= self::wrap(
378  $context->msg( 'parentheses' )
379  ->rawParams( $context->getLanguage()->pipeList( $links ) ),
380  'apihelp-linktrail', 'div'
381  );
382  }
383 
384  $flags = $module->getHelpFlags();
385  $help['flags'] .= Html::openElement( 'div',
386  [ 'class' => [ 'apihelp-block', 'apihelp-flags' ] ] );
387  $msg = $context->msg( 'api-help-flags' );
388  if ( !$msg->isDisabled() ) {
389  $help['flags'] .= self::wrap(
390  $msg->numParams( count( $flags ) ), 'apihelp-block-head', 'div'
391  );
392  }
393  $help['flags'] .= Html::openElement( 'ul' );
394  foreach ( $flags as $flag ) {
395  $help['flags'] .= Html::rawElement( 'li', [],
396  // The follow classes are used here:
397  // * apihelp-flag-generator
398  // * apihelp-flag-internal
399  // * apihelp-flag-mustbeposted
400  // * apihelp-flag-readrights
401  // * apihelp-flag-writerights
402  self::wrap( $context->msg( "api-help-flag-$flag" ), "apihelp-flag-$flag" )
403  );
404  }
405  $sourceInfo = $module->getModuleSourceInfo();
406  if ( $sourceInfo ) {
407  if ( isset( $sourceInfo['namemsg'] ) ) {
408  $extname = $context->msg( $sourceInfo['namemsg'] )->text();
409  } else {
410  // Probably English, so wrap it.
411  $extname = Html::element( 'span', [ 'dir' => 'ltr', 'lang' => 'en' ], $sourceInfo['name'] );
412  }
413  $help['flags'] .= Html::rawElement( 'li', [],
414  self::wrap(
415  $context->msg( 'api-help-source', $extname, $sourceInfo['name'] ),
416  'apihelp-source'
417  )
418  );
419 
420  $link = SpecialPage::getTitleFor( 'Version', 'License/' . $sourceInfo['name'] );
421  if ( isset( $sourceInfo['license-name'] ) ) {
422  $msg = $context->msg( 'api-help-license', $link,
423  Html::element( 'span', [ 'dir' => 'ltr', 'lang' => 'en' ], $sourceInfo['license-name'] )
424  );
425  } elseif ( ExtensionInfo::getLicenseFileNames( dirname( $sourceInfo['path'] ) ) ) {
426  $msg = $context->msg( 'api-help-license-noname', $link );
427  } else {
428  $msg = $context->msg( 'api-help-license-unknown' );
429  }
430  $help['flags'] .= Html::rawElement( 'li', [],
431  self::wrap( $msg, 'apihelp-license' )
432  );
433  } else {
434  $help['flags'] .= Html::rawElement( 'li', [],
435  self::wrap( $context->msg( 'api-help-source-unknown' ), 'apihelp-source' )
436  );
437  $help['flags'] .= Html::rawElement( 'li', [],
438  self::wrap( $context->msg( 'api-help-license-unknown' ), 'apihelp-license' )
439  );
440  }
441  $help['flags'] .= Html::closeElement( 'ul' );
442  $help['flags'] .= Html::closeElement( 'div' );
443 
444  foreach ( $module->getFinalDescription() as $msg ) {
445  $msg->setContext( $context );
446  $help['description'] .= $msg->parseAsBlock();
447  }
448 
449  $urls = $module->getHelpUrls();
450  if ( $urls ) {
451  if ( !is_array( $urls ) ) {
452  $urls = [ $urls ];
453  }
454  $help['help-urls'] .= Html::openElement( 'div',
455  [ 'class' => [ 'apihelp-block', 'apihelp-help-urls' ] ]
456  );
457  $msg = $context->msg( 'api-help-help-urls' );
458  if ( !$msg->isDisabled() ) {
459  $help['help-urls'] .= self::wrap(
460  $msg->numParams( count( $urls ) ), 'apihelp-block-head', 'div'
461  );
462  }
463  $help['help-urls'] .= Html::openElement( 'ul' );
464  foreach ( $urls as $url ) {
465  $help['help-urls'] .= Html::rawElement( 'li', [],
466  Html::element( 'a', [ 'href' => $url, 'dir' => 'ltr' ], $url )
467  );
468  }
469  $help['help-urls'] .= Html::closeElement( 'ul' );
470  $help['help-urls'] .= Html::closeElement( 'div' );
471  }
472 
473  $params = $module->getFinalParams( ApiBase::GET_VALUES_FOR_HELP );
474  $dynamicParams = $module->dynamicParameterDocumentation();
475  $groups = [];
476  if ( $params || $dynamicParams !== null ) {
477  $help['parameters'] .= Html::openElement( 'div',
478  [ 'class' => [ 'apihelp-block', 'apihelp-parameters' ] ]
479  );
480  $msg = $context->msg( 'api-help-parameters' );
481  if ( !$msg->isDisabled() ) {
482  $help['parameters'] .= self::wrap(
483  $msg->numParams( count( $params ) ), 'apihelp-block-head', 'div'
484  );
485  if ( !$module->isMain() ) {
486  // Add a note explaining that other parameters may exist.
487  $help['parameters'] .= self::wrap(
488  $context->msg( 'api-help-parameters-note' ), 'apihelp-block-header', 'div'
489  );
490  }
491  }
492  $help['parameters'] .= Html::openElement( 'dl' );
493 
494  $descriptions = $module->getFinalParamDescription();
495 
496  foreach ( $params as $name => $settings ) {
497  $settings = $paramValidator->normalizeSettings( $settings );
498 
499  if ( $settings[ParamValidator::PARAM_TYPE] === 'submodule' ) {
500  $groups[] = $name;
501  }
502 
503  $encodedParamName = $module->encodeParamName( $name );
504  $paramNameAttribs = [ 'dir' => 'ltr', 'lang' => 'en' ];
505  if ( isset( $anchor ) ) {
506  $paramNameAttribs['id'] = "$anchor:$encodedParamName";
507  }
508  $help['parameters'] .= Html::rawElement( 'dt', [],
509  Html::element( 'span', $paramNameAttribs, $encodedParamName )
510  );
511 
512  // Add description
513  $description = [];
514  if ( isset( $descriptions[$name] ) ) {
515  foreach ( $descriptions[$name] as $msg ) {
516  $msg->setContext( $context );
517  $description[] = $msg->parseAsBlock();
518  }
519  }
520  if ( !array_filter( $description ) ) {
521  $description = [ self::wrap(
522  $context->msg( 'api-help-param-no-description' ),
523  'apihelp-empty'
524  ) ];
525  }
526 
527  // Add "deprecated" flag
528  if ( !empty( $settings[ParamValidator::PARAM_DEPRECATED] ) ) {
529  $help['parameters'] .= Html::openElement( 'dd',
530  [ 'class' => 'info' ] );
531  $help['parameters'] .= self::wrap(
532  $context->msg( 'api-help-param-deprecated' ),
533  'apihelp-deprecated', 'strong'
534  );
535  $help['parameters'] .= Html::closeElement( 'dd' );
536  }
537 
538  if ( $description ) {
539  $description = implode( '', $description );
540  $description = preg_replace( '!\s*</([oud]l)>\s*<\1>\s*!', "\n", $description );
541  $help['parameters'] .= Html::rawElement( 'dd',
542  [ 'class' => 'description' ], $description );
543  }
544 
545  // Add usage info
546  $info = [];
547  $paramHelp = $paramValidator->getHelpInfo( $module, $name, $settings, [] );
548 
549  unset( $paramHelp[ParamValidator::PARAM_DEPRECATED] );
550 
551  if ( isset( $paramHelp[ParamValidator::PARAM_REQUIRED] ) ) {
552  $paramHelp[ParamValidator::PARAM_REQUIRED]->setContext( $context );
553  $info[] = $paramHelp[ParamValidator::PARAM_REQUIRED];
554  unset( $paramHelp[ParamValidator::PARAM_REQUIRED] );
555  }
556 
557  // Custom info?
558  if ( !empty( $settings[ApiBase::PARAM_HELP_MSG_INFO] ) ) {
559  foreach ( $settings[ApiBase::PARAM_HELP_MSG_INFO] as $i ) {
560  $tag = array_shift( $i );
561  $info[] = $context->msg( "apihelp-{$path}-paraminfo-{$tag}" )
562  ->numParams( count( $i ) )
563  ->params( $context->getLanguage()->commaList( $i ) )
564  ->params( $module->getModulePrefix() )
565  ->parse();
566  }
567  }
568 
569  // Templated?
570  if ( !empty( $settings[ApiBase::PARAM_TEMPLATE_VARS] ) ) {
571  $vars = [];
572  $msg = 'api-help-param-templated-var-first';
573  foreach ( $settings[ApiBase::PARAM_TEMPLATE_VARS] as $k => $v ) {
574  $vars[] = $context->msg( $msg, $k, $module->encodeParamName( $v ) );
575  $msg = 'api-help-param-templated-var';
576  }
577  $info[] = $context->msg( 'api-help-param-templated' )
578  ->numParams( count( $vars ) )
579  ->params( Message::listParam( $vars ) )
580  ->parse();
581  }
582 
583  // Type documentation
584  foreach ( $paramHelp as $m ) {
585  $m->setContext( $context );
586  $info[] = $m->parse();
587  }
588 
589  foreach ( $info as $i ) {
590  $help['parameters'] .= Html::rawElement( 'dd', [ 'class' => 'info' ], $i );
591  }
592  }
593 
594  if ( $dynamicParams !== null ) {
595  $dynamicParams = ApiBase::makeMessage( $dynamicParams, $context, [
596  $module->getModulePrefix(),
597  $module->getModuleName(),
598  $module->getModulePath()
599  ] );
600  $help['parameters'] .= Html::element( 'dt', [], '*' );
601  $help['parameters'] .= Html::rawElement( 'dd',
602  [ 'class' => 'description' ], $dynamicParams->parse() );
603  }
604 
605  $help['parameters'] .= Html::closeElement( 'dl' );
606  $help['parameters'] .= Html::closeElement( 'div' );
607  }
608 
609  $examples = $module->getExamplesMessages();
610  if ( $examples ) {
611  $help['examples'] .= Html::openElement( 'div',
612  [ 'class' => [ 'apihelp-block', 'apihelp-examples' ] ] );
613  $msg = $context->msg( 'api-help-examples' );
614  if ( !$msg->isDisabled() ) {
615  $help['examples'] .= self::wrap(
616  $msg->numParams( count( $examples ) ), 'apihelp-block-head', 'div'
617  );
618  }
619 
620  $help['examples'] .= Html::openElement( 'dl' );
621  foreach ( $examples as $qs => $msg ) {
622  $msg = ApiBase::makeMessage( $msg, $context, [
623  $module->getModulePrefix(),
624  $module->getModuleName(),
625  $module->getModulePath()
626  ] );
627 
628  $link = wfAppendQuery( wfScript( 'api' ), $qs );
629  $sandbox = SpecialPage::getTitleFor( 'ApiSandbox' )->getLocalURL() . '#' . $qs;
630  $help['examples'] .= Html::rawElement( 'dt', [], $msg->parse() );
631  $help['examples'] .= Html::rawElement( 'dd', [],
632  Html::element( 'a', [
633  'href' => $link,
634  'dir' => 'ltr',
635  'rel' => 'nofollow',
636  ], "api.php?$qs" ) . ' ' .
637  Html::rawElement( 'a', [ 'href' => $sandbox ],
638  $context->msg( 'api-help-open-in-apisandbox' )->parse() )
639  );
640  }
641  $help['examples'] .= Html::closeElement( 'dl' );
642  $help['examples'] .= Html::closeElement( 'div' );
643  }
644 
645  $subtocnumber = $tocnumber;
646  $subtocnumber[$level + 1] = 0;
647  $suboptions = [
648  'submodules' => $options['recursivesubmodules'],
649  'headerlevel' => $level + 1,
650  'tocnumber' => &$subtocnumber,
651  'noheader' => false,
652  ] + $options;
653 
654  // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset False positive
655  if ( $options['submodules'] && $module->getModuleManager() ) {
656  $manager = $module->getModuleManager();
657  $submodules = [];
658  foreach ( $groups as $group ) {
659  $names = $manager->getNames( $group );
660  sort( $names );
661  foreach ( $names as $name ) {
662  $submodules[] = $manager->getModule( $name );
663  }
664  }
665  $help['submodules'] .= self::getHelpInternal(
666  $context,
667  $submodules,
668  $suboptions,
669  $haveModules
670  );
671  }
672 
673  $module->modifyHelp( $help, $suboptions, $haveModules );
674 
675  $module->getHookRunner()->onAPIHelpModifyOutput( $module, $help,
676  $suboptions, $haveModules );
677 
678  $out .= implode( "\n", $help );
679  }
680 
681  return $out;
682  }
683 
684  public function shouldCheckMaxlag() {
685  return false;
686  }
687 
688  public function isReadMode() {
689  return false;
690  }
691 
692  public function getCustomPrinter() {
693  $params = $this->extractRequestParams();
694  if ( $params['wrap'] ) {
695  return null;
696  }
697 
698  $main = $this->getMain();
699  $errorPrinter = $main->createPrinterByName( $main->getParameter( 'format' ) );
700  return new ApiFormatRaw( $main, $errorPrinter );
701  }
702 
703  public function getAllowedParams() {
704  return [
705  'modules' => [
706  ParamValidator::PARAM_DEFAULT => 'main',
707  ParamValidator::PARAM_ISMULTI => true,
708  ],
709  'submodules' => false,
710  'recursivesubmodules' => false,
711  'wrap' => false,
712  'toc' => false,
713  ];
714  }
715 
716  protected function getExamplesMessages() {
717  return [
718  'action=help'
719  => 'apihelp-help-example-main',
720  'action=help&modules=query&submodules=1'
721  => 'apihelp-help-example-submodules',
722  'action=help&recursivesubmodules=1'
723  => 'apihelp-help-example-recursive',
724  'action=help&modules=help'
725  => 'apihelp-help-example-help',
726  'action=help&modules=query+info|query+categorymembers'
727  => 'apihelp-help-example-query',
728  ];
729  }
730 
731  public function getHelpUrls() {
732  return [
733  'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Main_page',
734  'https://www.mediawiki.org/wiki/Special:MyLanguage/API:FAQ',
735  'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Quick_start_guide',
736  ];
737  }
738 }
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
wfScript( $script='index')
Get the URL path to a MediaWiki entry point.
$modules
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:62
getModuleFromPath( $path)
Get a module from its module path.
Definition: ApiBase.php:627
static makeMessage( $msg, IContextSource $context, array $params=null)
Create a Message from a string or array.
Definition: ApiBase.php:1267
getMain()
Get the main module.
Definition: ApiBase.php:546
const PARAM_HELP_MSG_INFO
(array) Specify additional information tags for the parameter.
Definition: ApiBase.php:186
const PARAM_TEMPLATE_VARS
(array) Indicate that this is a templated parameter, and specify replacements.
Definition: ApiBase.php:227
getResult()
Get the result object.
Definition: ApiBase.php:667
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:807
getModulePath()
Get the path to this module.
Definition: ApiBase.php:607
const GET_VALUES_FOR_HELP
getAllowedParams() flag: When this is set, the result could take longer to generate,...
Definition: ApiBase.php:247
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:528
Formatter that spits out anything you like with any desired MIME type.
Class to output help for an API module.
Definition: ApiHelp.php:43
isReadMode()
Indicates whether this module requires read rights.
Definition: ApiHelp.php:688
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
Definition: ApiHelp.php:60
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiHelp.php:716
static fixHelpLinks( $html, $helptitle=null, $localModules=[])
Replace Special:ApiHelp links with links to api.php.
Definition: ApiHelp.php:215
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiHelp.php:703
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiHelp.php:731
static getHelp(IContextSource $context, $modules, array $options)
Generate help for the specified modules.
Definition: ApiHelp.php:139
shouldCheckMaxlag()
Indicates if this module needs maxlag to be checked.
Definition: ApiHelp.php:684
__construct(ApiMain $main, $action, SkinFactory $skinFactory)
Definition: ApiHelp.php:51
getCustomPrinter()
If the module may only be used with a certain format module, it should override this method to return...
Definition: ApiHelp.php:692
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:64
const NO_SIZE_CHECK
For addValue() and similar functions, do not check size while adding a value Don't use this unless yo...
Definition: ApiResult.php:58
static setSubelementsList(array &$arr, $names)
Causes the elements with the specified names to be output as subelements rather than attributes.
Definition: ApiResult.php:553
getContext()
Get the base IContextSource object.
An IContextSource implementation which will inherit context from another source but allow individual ...
const UTF8_OK
Skip escaping most characters above U+007F for readability and compactness.
Definition: FormatJson.php:36
static encode( $value, $pretty=false, $escaping=0)
Returns the JSON representation of a value.
Definition: FormatJson.php:98
Static utilities for manipulating HTML strings.
Definition: HtmlHelper.php:17
This class is a collection of static functions that serve two purposes:
Definition: Html.php:57
Some internal bits split of from Skin.php.
Definition: Linker.php:65
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
This is one of the Core classes and should be read at least once by any new developers.
Definition: OutputPage.php:93
Parent class for all special pages.
Definition: SpecialPage.php:65
Give information about the version of MediaWiki, PHP, the DB and extensions.
Represents a title within MediaWiki.
Definition: Title.php:76
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition: Message.php:144
static listParam(array $list, $type='text')
Definition: Message.php:1286
parse()
Fully parse the text from wikitext to HTML.
Definition: Message.php:1045
Factory class to create Skin objects.
Definition: SkinFactory.php:31
Service for formatting and validating API parameters.
Interface for objects which can provide a MediaWiki context on request.
getConfig()
Get the site configuration.
msg( $key,... $params)
This is the method for getting translated interface messages.
return true
Definition: router.php:90