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