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