23use HtmlFormatter\HtmlFormatter;
29use Wikimedia\Assert\Assert;
91 public static function link(
92 $target, $html =
null, $customAttribs = [], $query = [], $options = []
95 wfWarn( __METHOD__ .
': Requires $target to be a LinkTarget object.', 2 );
96 return "<!-- ERROR -->$html";
99 $services = MediaWikiServices::getInstance();
100 $options = (array)$options;
103 $linkRenderer = $services->getLinkRendererFactory()
104 ->createFromLegacyOptions( $options );
106 $linkRenderer = $services->getLinkRenderer();
109 if ( $html !==
null ) {
115 if ( in_array(
'known', $options,
true ) ) {
116 return $linkRenderer->makeKnownLink( $target, $text, $customAttribs, $query );
119 if ( in_array(
'broken', $options,
true ) ) {
120 return $linkRenderer->makeBrokenLink( $target, $text, $customAttribs, $query );
123 if ( in_array(
'noclasses', $options,
true ) ) {
124 return $linkRenderer->makePreloadedLink( $target, $text,
'', $customAttribs, $query );
127 return $linkRenderer->makeLink( $target, $text, $customAttribs, $query );
144 $target, $html =
null, $customAttribs = [],
145 $query = [], $options = [
'known' ]
147 return self::link( $target, $html, $customAttribs, $query, $options );
165 public static function makeSelfLinkObj( $nt, $html =
'', $query =
'', $trail =
'', $prefix =
'' ) {
166 $nt = Title::newFromLinkTarget( $nt );
167 $ret =
"<a class=\"mw-selflink selflink\">{$prefix}{$html}</a>{$trail}";
168 if ( !Hooks::runner()->onSelfLinkBegin( $nt, $html, $trail, $prefix, $ret ) ) {
173 $html = htmlspecialchars( $nt->getPrefixedText() );
176 return "<a class=\"mw-selflink selflink\">{$prefix}{$html}{$inside}</a>{$trail}";
191 if ( MediaWikiServices::getInstance()->getNamespaceInfo()->exists( $namespace ) ) {
193 $name = $context->
msg(
'blanknamespace' )->text();
195 $name = MediaWikiServices::getInstance()->getContentLanguage()->
196 getFormattedNsText( $namespace );
198 return $context->
msg(
'invalidtitle-knownnamespace', $namespace, $name,
$title )->text();
201 return $context->
msg(
'invalidtitle-unknownnamespace', $namespace,
$title )->text();
212 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
213 return $linkRenderer->normalizeTarget( $target );
224 private static function fnamePart( $url ) {
225 $basename = strrchr( $url,
'/' );
226 if ( $basename ===
false ) {
229 $basename = substr( $basename, 1 );
246 $alt = self::fnamePart( $url );
249 $success = Hooks::runner()->onLinkerMakeExternalImage( $url, $alt, $img );
251 wfDebug(
"Hook LinkerMakeExternalImage changed the output of external image "
252 .
"with url {$url} and alt text {$alt} to {$img}" );
255 return Html::element(
'img',
302 $file, $frameParams = [], $handlerParams = [], $time =
false,
303 $query =
'', $widthOption =
null
308 if ( !Hooks::runner()->onImageBeforeProduceHTML( $dummy,
$title,
310 $file, $frameParams, $handlerParams, $time,
$res,
312 $parser, $query, $widthOption )
317 if (
$file && !
$file->allowInlineDisplay() ) {
318 wfDebug( __METHOD__ .
': ' .
$title->getPrefixedDBkey() .
' does not allow inline display' );
323 $page = $handlerParams[
'page'] ??
false;
324 if ( !isset( $frameParams[
'align'] ) ) {
325 $frameParams[
'align'] =
'';
327 if ( !isset( $frameParams[
'alt'] ) ) {
328 $frameParams[
'alt'] =
'';
330 if ( !isset( $frameParams[
'title'] ) ) {
331 $frameParams[
'title'] =
'';
333 if ( !isset( $frameParams[
'class'] ) ) {
334 $frameParams[
'class'] =
'';
337 $services = MediaWikiServices::getInstance();
338 $config = $services->getMainConfig();
339 $enableLegacyMediaDOM = $config->get( MainConfigNames::ParserEnableLegacyMediaDOM );
343 !isset( $handlerParams[
'width'] ) &&
344 !isset( $frameParams[
'manualthumb'] ) &&
345 !isset( $frameParams[
'framed'] )
347 $classes[] =
'mw-default-size';
350 $prefix = $postfix =
'';
352 if ( $enableLegacyMediaDOM ) {
353 if ( $frameParams[
'align'] ==
'center' ) {
354 $prefix =
'<div class="center">';
356 $frameParams[
'align'] =
'none';
360 if (
$file && !isset( $handlerParams[
'width'] ) ) {
361 if ( isset( $handlerParams[
'height'] ) &&
$file->isVectorized() ) {
364 $svgMaxSize = $config->get( MainConfigNames::SVGMaxSize );
365 $handlerParams[
'width'] = $svgMaxSize;
367 $handlerParams[
'width'] =
$file->getWidth( $page );
370 if ( isset( $frameParams[
'thumbnail'] )
371 || isset( $frameParams[
'manualthumb'] )
372 || isset( $frameParams[
'framed'] )
373 || isset( $frameParams[
'frameless'] )
374 || !$handlerParams[
'width']
376 $thumbLimits = $config->get( MainConfigNames::ThumbLimits );
377 $thumbUpright = $config->get( MainConfigNames::ThumbUpright );
378 if ( $widthOption ===
null || !isset( $thumbLimits[$widthOption] ) ) {
379 $userOptionsLookup = $services->getUserOptionsLookup();
380 $widthOption = $userOptionsLookup->getDefaultOption(
'thumbsize' );
384 if ( isset( $frameParams[
'upright'] ) && $frameParams[
'upright'] == 0 ) {
385 $frameParams[
'upright'] = $thumbUpright;
391 $prefWidth = isset( $frameParams[
'upright'] ) ?
392 round( $thumbLimits[$widthOption] * $frameParams[
'upright'], -1 ) :
393 $thumbLimits[$widthOption];
397 if ( !isset( $handlerParams[
'height'] ) && ( $handlerParams[
'width'] <= 0 ||
398 $prefWidth < $handlerParams[
'width'] ||
$file->isVectorized() ) ) {
399 $handlerParams[
'width'] = $prefWidth;
405 $hasVisibleCaption = isset( $frameParams[
'thumbnail'] ) ||
406 isset( $frameParams[
'manualthumb'] ) ||
407 isset( $frameParams[
'framed'] );
409 if ( $hasVisibleCaption ) {
410 if ( $enableLegacyMediaDOM ) {
415 # Create a thumbnail. Alignment depends on the writing direction of
416 # the page content language (right-aligned for LTR languages,
417 # left-aligned for RTL languages)
418 # If a thumbnail width has not been provided, it is set
419 # to the default user option as specified in Language*.php
420 if ( $frameParams[
'align'] ==
'' ) {
425 $title,
$file, $frameParams, $handlerParams, $time, $query,
430 $rdfaType =
'mw:File';
432 if ( isset( $frameParams[
'frameless'] ) ) {
433 $rdfaType .=
'/Frameless';
435 $srcWidth =
$file->getWidth( $page );
436 # For "frameless" option: do not present an image bigger than the
437 # source (for bitmap-style images). This is the same behavior as the
438 # "thumb" option does it already.
439 if ( $srcWidth && !
$file->mustRender() && $handlerParams[
'width'] > $srcWidth ) {
440 $handlerParams[
'width'] = $srcWidth;
445 if (
$file && isset( $handlerParams[
'width'] ) ) {
446 # Create a resized image, without the additional thumbnail features
447 $thumb =
$file->transform( $handlerParams );
452 $isBadFile =
$file && $thumb &&
455 if ( !$thumb || ( !$enableLegacyMediaDOM && $thumb->isError() ) || $isBadFile ) {
456 $rdfaType =
'mw:Error ' . $rdfaType;
458 if ( $enableLegacyMediaDOM ) {
461 $label = $frameParams[
'title'];
463 if ( $currentExists && !$thumb ) {
464 $label =
wfMessage(
'thumbnail_error',
'' )->text();
465 } elseif ( $thumb && $thumb->isError() ) {
468 'Unknown MediaTransformOutput: ' . get_class( $thumb )
470 $label = $thumb->toText();
476 $title, $label,
'',
'',
'', (
bool)$time, $handlerParams, $currentExists
481 'alt' => $frameParams[
'alt'],
482 'title' => $frameParams[
'title'],
484 if ( $enableLegacyMediaDOM ) {
486 'valign' => $frameParams[
'valign'] ??
false,
487 'img-class' => $frameParams[
'class'],
489 if ( isset( $frameParams[
'border'] ) ) {
490 $params[
'img-class'] .= ( $params[
'img-class'] !==
'' ?
' ' :
'' ) .
'thumbborder';
494 $s = $thumb->toHtml( $params );
497 if ( $enableLegacyMediaDOM ) {
498 if ( $frameParams[
'align'] !=
'' ) {
499 $s = Html::rawElement(
501 [
'class' =>
'float' . $frameParams[
'align'] ],
505 return str_replace(
"\n",
' ', $prefix .
$s . $postfix );
511 if ( $frameParams[
'align'] !=
'' ) {
514 $classes[] =
"mw-halign-{$frameParams['align']}";
515 $caption = Html::rawElement(
516 'figcaption', [], $frameParams[
'caption'] ??
''
518 } elseif ( isset( $frameParams[
'valign'] ) ) {
522 $classes[] =
"mw-valign-{$frameParams['valign']}";
525 if ( isset( $frameParams[
'border'] ) ) {
526 $classes[] =
'mw-image-border';
529 if ( isset( $frameParams[
'class'] ) ) {
530 $classes[] = $frameParams[
'class'];
535 'typeof' => $rdfaType,
538 $s = Html::rawElement( $wrapper, $attribs,
$s . $caption );
540 return str_replace(
"\n",
' ',
$s );
553 if ( isset( $frameParams[
'link-url'] ) && $frameParams[
'link-url'] !==
'' ) {
554 $mtoParams[
'custom-url-link'] = $frameParams[
'link-url'];
555 if ( isset( $frameParams[
'link-target'] ) ) {
556 $mtoParams[
'custom-target-link'] = $frameParams[
'link-target'];
559 $extLinkAttrs = $parser->getExternalLinkAttribs( $frameParams[
'link-url'] );
560 foreach ( $extLinkAttrs as $name => $val ) {
562 $mtoParams[
'parser-extlink-' . $name] = $val;
565 } elseif ( isset( $frameParams[
'link-title'] ) && $frameParams[
'link-title'] !==
'' ) {
566 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
567 $mtoParams[
'custom-title-link'] = Title::newFromLinkTarget(
568 $linkRenderer->normalizeTarget( $frameParams[
'link-title'] )
570 if ( isset( $frameParams[
'link-title-query'] ) ) {
571 $mtoParams[
'custom-title-link-query'] = $frameParams[
'link-title-query'];
573 } elseif ( !empty( $frameParams[
'no-link'] ) ) {
576 $mtoParams[
'desc-link'] =
true;
577 $mtoParams[
'desc-query'] = $query;
596 $params = [], $framed =
false, $manualthumb =
''
604 if ( $manualthumb ) {
605 $frameParams[
'manualthumb'] = $manualthumb;
606 } elseif ( $framed ) {
607 $frameParams[
'framed'] =
true;
608 } elseif ( !isset( $params[
'width'] ) ) {
609 $classes[] =
'mw-default-size';
612 $title,
$file, $frameParams, $params,
false,
'', $classes
629 $time =
false, $query =
'', array $classes = [], ?
Parser $parser =
null
633 $services = MediaWikiServices::getInstance();
634 $enableLegacyMediaDOM = $services->getMainConfig()->get( MainConfigNames::ParserEnableLegacyMediaDOM );
636 $page = $handlerParams[
'page'] ??
false;
637 if ( !isset( $frameParams[
'align'] ) ) {
638 $frameParams[
'align'] =
'';
639 if ( $enableLegacyMediaDOM ) {
640 $frameParams[
'align'] =
'right';
643 if ( !isset( $frameParams[
'alt'] ) ) {
644 $frameParams[
'alt'] =
'';
646 if ( !isset( $frameParams[
'caption'] ) ) {
647 $frameParams[
'caption'] =
'';
650 if ( empty( $handlerParams[
'width'] ) ) {
652 $handlerParams[
'width'] = isset( $frameParams[
'upright'] ) ? 130 : 180;
657 $manualthumb =
false;
659 $rdfaType =
'mw:File/Thumb';
663 if ( !isset( $frameParams[
'manualthumb'] ) && isset( $frameParams[
'framed'] ) ) {
664 $rdfaType =
'mw:File/Frame';
666 $outerWidth = $handlerParams[
'width'] + 2;
668 if ( isset( $frameParams[
'manualthumb'] ) ) {
669 # Use manually specified thumbnail
670 $manual_title = Title::makeTitleSafe(
NS_FILE, $frameParams[
'manualthumb'] );
671 if ( $manual_title ) {
672 $manual_img = $services->getRepoGroup()
673 ->findFile( $manual_title );
675 $thumb = $manual_img->getUnscaledThumb( $handlerParams );
679 } elseif ( isset( $frameParams[
'framed'] ) ) {
681 $thumb =
$file->getUnscaledThumb( $handlerParams );
683 $rdfaType =
'mw:File/Frame';
685 # Do not present an image bigger than the source, for bitmap-style images
686 # This is a hack to maintain compatibility with arbitrary pre-1.10 behavior
687 $srcWidth =
$file->getWidth( $page );
688 if ( $srcWidth && !
$file->mustRender() && $handlerParams[
'width'] > $srcWidth ) {
689 $handlerParams[
'width'] = $srcWidth;
691 $thumb =
$file->transform( $handlerParams );
695 $outerWidth = $thumb->getWidth() + 2;
697 $outerWidth = $handlerParams[
'width'] + 2;
701 $url = Title::newFromLinkTarget(
$title )->getLocalURL( $query );
702 $linkTitleQuery = [];
705 $linkTitleQuery[
'page'] = $page;
706 # ThumbnailImage::toHtml() already adds page= onto the end of DjVu URLs
707 # So we don't need to pass it here in $query. However, the URL for the
708 # zoom icon still needs it, so we make a unique query for it. See T16771
709 # FIXME: What about "lang" and other querystring parameters
714 && !isset( $frameParams[
'link-title'] )
715 && !isset( $frameParams[
'link-url'] )
716 && !isset( $frameParams[
'no-link'] ) ) {
717 $frameParams[
'link-title'] =
$title;
718 $frameParams[
'link-title-query'] = $linkTitleQuery;
721 if ( $frameParams[
'align'] !=
'' ) {
723 $classes[] =
"mw-halign-{$frameParams['align']}";
726 if ( isset( $frameParams[
'class'] ) ) {
727 $classes[] = $frameParams[
'class'];
732 if ( $enableLegacyMediaDOM ) {
733 $s .=
"<div class=\"thumb t{$frameParams['align']}\">"
734 .
"<div class=\"thumbinner\" style=\"width:{$outerWidth}px;\">";
737 $isBadFile = $exists && $thumb && $parser &&
738 $parser->getBadFileLookup()->isBadFile(
739 $manualthumb ? $manual_title :
$title->getDBkey(),
744 $rdfaType =
'mw:Error ' . $rdfaType;
747 $title, $label,
'',
'',
'', (
bool)$time, $handlerParams,
false
750 } elseif ( !$thumb || ( !$enableLegacyMediaDOM && $thumb->isError() ) || $isBadFile ) {
751 $rdfaType =
'mw:Error ' . $rdfaType;
752 if ( $enableLegacyMediaDOM ) {
754 $s .=
wfMessage(
'thumbnail_error',
'' )->escaped();
757 $title,
'',
'',
'',
'', (
bool)$time, $handlerParams,
true
761 if ( $thumb && $thumb->isError() ) {
764 'Unknown MediaTransformOutput: ' . get_class( $thumb )
766 $label = $thumb->toText();
767 } elseif ( !$thumb ) {
768 $label =
wfMessage(
'thumbnail_error',
'' )->text();
773 $title, $label,
'',
'',
'', (
bool)$time, $handlerParams,
true
778 if ( !$noscale && !$manualthumb ) {
782 'alt' => $frameParams[
'alt'],
784 if ( $enableLegacyMediaDOM ) {
786 'img-class' => ( isset( $frameParams[
'class'] ) && $frameParams[
'class'] !==
''
787 ? $frameParams[
'class'] .
' '
788 :
'' ) .
'thumbimage'
792 $s .= $thumb->toHtml( $params );
793 if ( isset( $frameParams[
'framed'] ) ) {
796 $zoomIcon = Html::rawElement(
'div', [
'class' =>
'magnify' ],
797 Html::rawElement(
'a', [
799 'class' =>
'internal',
800 'title' =>
wfMessage(
'thumbnail-more' )->text(),
806 if ( $enableLegacyMediaDOM ) {
807 $s .=
' <div class="thumbcaption">' . $zoomIcon . $frameParams[
'caption'] .
'</div></div></div>';
808 return str_replace(
"\n",
' ',
$s );
811 $s .= Html::rawElement(
812 'figcaption', [], $frameParams[
'caption'] ??
''
817 'typeof' => $rdfaType,
820 $s = Html::rawElement(
'figure', $attribs,
$s );
822 return str_replace(
"\n",
' ',
$s );
834 $responsiveImages = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::ResponsiveImages );
835 if ( $responsiveImages && $thumb && !$thumb->isError() ) {
837 $hp15[
'width'] = round( $hp[
'width'] * 1.5 );
839 $hp20[
'width'] = $hp[
'width'] * 2;
840 if ( isset( $hp[
'height'] ) ) {
841 $hp15[
'height'] = round( $hp[
'height'] * 1.5 );
842 $hp20[
'height'] = $hp[
'height'] * 2;
845 $thumb15 =
$file->transform( $hp15 );
846 $thumb20 =
$file->transform( $hp20 );
847 if ( $thumb15 && !$thumb15->isError() && $thumb15->getUrl() !== $thumb->getUrl() ) {
848 $thumb->responsiveUrls[
'1.5'] = $thumb15->getUrl();
850 if ( $thumb20 && !$thumb20->isError() && $thumb20->getUrl() !== $thumb->getUrl() ) {
851 $thumb->responsiveUrls[
'2'] = $thumb20->getUrl();
871 $title, $label =
'', $query =
'', $unused1 =
'', $unused2 =
'',
872 $time =
false, array $handlerParams = [],
bool $currentExists =
false
875 wfWarn( __METHOD__ .
': Requires $title to be a LinkTarget object.' );
876 return "<!-- ERROR -->" . htmlspecialchars( $label );
880 $services = MediaWikiServices::getInstance();
881 $mainConfig = $services->getMainConfig();
882 $enableUploads = $mainConfig->get( MainConfigNames::EnableUploads );
883 $uploadMissingFileUrl = $mainConfig->get( MainConfigNames::UploadMissingFileUrl );
884 $uploadNavigationUrl = $mainConfig->get( MainConfigNames::UploadNavigationUrl );
885 if ( $label ==
'' ) {
886 $label =
$title->getPrefixedText();
889 $html = Html::element(
'span', [
890 'class' =>
'mw-broken-media',
892 'data-width' => $handlerParams[
'width'] ??
null,
893 'data-height' => $handlerParams[
'height'] ??
null,
896 if ( $mainConfig->get( MainConfigNames::ParserEnableLegacyMediaDOM ) ) {
897 $html = htmlspecialchars( $label, ENT_COMPAT );
900 $repoGroup = $services->getRepoGroup();
901 $currentExists = $currentExists ||
902 ( $time && $repoGroup->findFile(
$title ) !== false );
904 if ( ( $uploadMissingFileUrl || $uploadNavigationUrl || $enableUploads )
909 $repoGroup->getLocalRepo()->checkRedirect(
$title )
915 [
'class' =>
'mw-redirect' ],
917 [
'known',
'noclasses' ]
920 return Html::rawElement(
'a', [
921 'href' => self::getUploadUrl(
$title, $query ),
923 'title' =>
$title->getPrefixedText()
931 [
'known',
'noclasses' ]
944 $mainConfig = MediaWikiServices::getInstance()->getMainConfig();
945 $uploadMissingFileUrl = $mainConfig->get( MainConfigNames::UploadMissingFileUrl );
946 $uploadNavigationUrl = $mainConfig->get( MainConfigNames::UploadNavigationUrl );
947 $q =
'wpDestFile=' . Title::castFromLinkTarget( $destFile )->getPartialURL();
948 if ( $query !=
'' ) {
952 if ( $uploadMissingFileUrl ) {
956 if ( $uploadNavigationUrl ) {
962 return $upload->getLocalURL( $q );
975 $img = MediaWikiServices::getInstance()->getRepoGroup()->findFile(
976 $title, [
'time' => $time ]
995 $url =
$file->getUrl();
1002 $alt =
$title->getText();
1003 if ( $html ==
'' ) {
1014 if ( !Hooks::runner()->onLinkerMakeMediaLinkFile(
1015 Title::castFromLinkTarget(
$title ),
$file, $html, $attribs, $ret )
1017 wfDebug(
"Hook LinkerMakeMediaLinkFile changed the output of link "
1018 .
"with url {$url} and text {$html} to {$ret}" );
1022 return Html::rawElement(
'a', $attribs, $html );
1037 $key = strtolower( $name );
1062 $linktype =
'', $attribs = [],
$title =
null
1065 $class =
'external';
1067 $class .=
" $linktype";
1069 if ( isset( $attribs[
'class'] ) && $attribs[
'class'] ) {
1070 $class .=
" {$attribs['class']}";
1072 $attribs[
'class'] = $class;
1075 $text = htmlspecialchars( $text, ENT_COMPAT );
1082 if ( !isset( $attribs[
'rel'] ) || $attribs[
'rel'] ===
'' ) {
1083 $attribs[
'rel'] = $newRel;
1084 } elseif ( $newRel !==
null ) {
1086 $newRels = explode(
' ', $newRel );
1087 $oldRels = explode(
' ', $attribs[
'rel'] );
1088 $combined = array_unique( array_merge( $newRels, $oldRels ) );
1089 $attribs[
'rel'] = implode(
' ', $combined );
1092 $success = Hooks::runner()->onLinkerMakeExternalLink(
1093 $url, $text, $link, $attribs, $linktype );
1095 wfDebug(
"Hook LinkerMakeExternalLink changed the output of link "
1096 .
"with url {$url} and text {$text} to {$link}" );
1099 $attribs[
'href'] = $url;
1100 return Html::rawElement(
'a', $attribs, $text );
1114 public static function userLink( $userId, $userName, $altUserName =
false ) {
1115 if ( $userName ===
'' || $userName ===
false || $userName ===
null ) {
1116 wfDebug( __METHOD__ .
' received an empty username. Are there database errors ' .
1117 'that need to be fixed?' );
1118 return wfMessage(
'empty-username' )->parse();
1121 $classes =
'mw-userlink';
1123 if ( $userId == 0 ) {
1124 $page = ExternalUserNames::getUserLinkTitle( $userName );
1126 if ( ExternalUserNames::isExternal( $userName ) ) {
1127 $classes .=
' mw-extuserlink';
1128 } elseif ( $altUserName ===
false ) {
1129 $altUserName = IPUtils::prettifyIP( $userName );
1131 $classes .=
' mw-anonuserlink';
1133 $page = TitleValue::tryNew(
NS_USER, strtr( $userName,
' ',
'_' ) );
1138 '<bdi>' . htmlspecialchars( $altUserName !==
false ? $altUserName : $userName ) .
'</bdi>';
1141 ?
self::link( $page, $linkText, [
'class' => $classes ] )
1142 : Html::rawElement(
'span', [
'class' => $classes ], $linkText );
1160 $userId, $userText, $redContribsWhenNoEdits =
false, $flags = 0, $edits =
null,
1161 $useParentheses =
true
1163 if ( $userText ===
'' ) {
1164 wfDebug( __METHOD__ .
' received an empty username. Are there database errors ' .
1165 'that need to be fixed?' );
1166 return ' ' .
wfMessage(
'empty-username' )->parse();
1169 $disableAnonTalk = MediaWikiServices::getInstance()->getMainConfig()->get( MainConfigNames::DisableAnonTalk );
1170 $talkable = !( $disableAnonTalk && $userId == 0 );
1172 $addEmailLink = $flags & self::TOOL_LINKS_EMAIL && $userId;
1174 if ( $userId == 0 && ExternalUserNames::isExternal( $userText ) ) {
1186 $attribs[
'class'] =
'mw-usertoollinks-contribs';
1187 if ( $redContribsWhenNoEdits ) {
1188 if ( intval( $edits ) === 0 && $edits !== 0 ) {
1190 $edits = $user->getEditCount();
1192 if ( $edits === 0 ) {
1195 $attribs[
'class'] .=
' mw-usertoollinks-contribs-no-edits';
1202 $userCanBlock = RequestContext::getMain()->getAuthority()->isAllowed(
'block' );
1203 if ( $blockable && $userCanBlock ) {
1207 $user = RequestContext::getMain()->getUser();
1208 if ( $addEmailLink && $user->canSendEmail() ) {
1212 Hooks::runner()->onUserToolLinksEdit( $userId, $userText, $items );
1218 if ( $useParentheses ) {
1219 return wfMessage(
'word-separator' )->escaped()
1220 .
'<span class="mw-usertoollinks">'
1221 .
wfMessage(
'parentheses' )->rawParams(
$wgLang->pipeList( $items ) )->escaped()
1226 foreach ( $items as $tool ) {
1227 $tools[] = Html::rawElement(
'span', [], $tool );
1229 return ' <span class="mw-usertoollinks mw-changeslist-links">' .
1230 implode(
' ', $tools ) .
'</span>';
1243 $userId, $userText, $edits =
null, $useParentheses =
true
1255 if ( $userText ===
'' ) {
1256 wfDebug( __METHOD__ .
' received an empty username. Are there database errors ' .
1257 'that need to be fixed?' );
1258 return wfMessage(
'empty-username' )->parse();
1261 $userTalkPage = TitleValue::tryNew(
NS_USER_TALK, strtr( $userText,
' ',
'_' ) );
1262 $moreLinkAttribs = [
'class' =>
'mw-usertoollinks-talk' ];
1263 $linkText =
wfMessage(
'talkpagelinktext' )->escaped();
1265 return $userTalkPage
1266 ?
self::link( $userTalkPage, $linkText, $moreLinkAttribs )
1267 : Html::rawElement(
'span', $moreLinkAttribs, $linkText );
1277 if ( $userText ===
'' ) {
1278 wfDebug( __METHOD__ .
' received an empty username. Are there database errors ' .
1279 'that need to be fixed?' );
1280 return wfMessage(
'empty-username' )->parse();
1284 $moreLinkAttribs = [
'class' =>
'mw-usertoollinks-block' ];
1298 if ( $userText ===
'' ) {
1299 wfLogWarning( __METHOD__ .
' received an empty username. Are there database errors ' .
1300 'that need to be fixed?' );
1301 return wfMessage(
'empty-username' )->parse();
1305 $moreLinkAttribs = [
'class' =>
'mw-usertoollinks-mail' ];
1325 $authority = RequestContext::getMain()->getAuthority();
1327 if ( $revRecord->
isDeleted( RevisionRecord::DELETED_USER ) && $isPublic ) {
1328 $link =
wfMessage(
'rev-deleted-user' )->escaped();
1329 } elseif ( $revRecord->
userCan( RevisionRecord::DELETED_USER, $authority ) ) {
1330 $revUser = $revRecord->
getUser( RevisionRecord::FOR_THIS_USER, $authority );
1332 $revUser ? $revUser->getId() : 0,
1333 $revUser ? $revUser->getName() :
''
1336 $link =
wfMessage(
'rev-deleted-user' )->escaped();
1338 if ( $revRecord->
isDeleted( RevisionRecord::DELETED_USER ) ) {
1340 return '<span class="' . $class .
'">' . $link .
'</span>';
1352 $class =
'history-deleted';
1353 if ( $revisionRecord->
isDeleted( RevisionRecord::DELETED_RESTRICTED ) ) {
1354 $class .=
' mw-history-suppressed';
1374 $useParentheses =
true
1377 $authority = RequestContext::getMain()->getAuthority();
1379 if ( $revRecord->
userCan( RevisionRecord::DELETED_USER, $authority ) &&
1380 ( !$revRecord->
isDeleted( RevisionRecord::DELETED_USER ) || !$isPublic )
1382 $revUser = $revRecord->
getUser( RevisionRecord::FOR_THIS_USER, $authority );
1383 $userId = $revUser ? $revUser->getId() : 0;
1384 $userText = $revUser ? $revUser->getName() :
'';
1386 if ( $userId || $userText !==
'' ) {
1387 $link = self::userLink( $userId, $userText )
1388 . self::userToolLinks( $userId, $userText,
false, 0,
null,
1393 if ( !isset( $link ) ) {
1394 $link =
wfMessage(
'rev-deleted-user' )->escaped();
1397 if ( $revRecord->
isDeleted( RevisionRecord::DELETED_USER ) ) {
1398 $class = self::getRevisionDeletedClass( $revRecord );
1399 return ' <span class="' . $class .
' mw-userlink">' . $link .
'</span>';
1415 $formatter =
new HtmlFormatter( $html );
1416 $doc = $formatter->getDoc();
1417 $xpath =
new DOMXPath( $doc );
1418 $nodes = $xpath->query(
'//a[@href]' );
1420 foreach ( $nodes as $node ) {
1421 $node->setAttribute(
1426 return $formatter->getText(
'html' );
1450 $comment,
$title =
null, $local =
false, $wikiId =
null
1452 $formatter = MediaWikiServices::getInstance()->getCommentFormatter();
1453 return $formatter->format( $comment,
$title, $local, $wikiId );
1476 $comment,
$title =
null, $local =
false, $wikiId =
null
1478 $formatter = MediaWikiServices::getInstance()->getCommentFormatter();
1479 return $formatter->formatLinksUnsafe( $comment,
$title, $local, $wikiId );
1491 # :Foobar -- override special treatment of prefix (images, language links)
1492 # /Foobar -- convert to CurrentPage/Foobar
1493 # /Foobar/ -- convert to CurrentPage/Foobar, strip the initial and final / from text
1494 # ../ -- convert to CurrentPage, from CurrentPage/CurrentSubPage
1495 # ../Foobar -- convert to CurrentPage/Foobar,
1496 # (from CurrentPage/CurrentSubPage)
1497 # ../Foobar/ -- convert to CurrentPage/Foobar, use 'Foobar' as text
1498 # (from CurrentPage/CurrentSubPage)
1500 $ret = $target; #
default return value is no change
1502 # Some namespaces don't allow subpages,
1503 # so only perform processing if subpages are allowed
1505 $contextTitle && MediaWikiServices::getInstance()->getNamespaceInfo()->
1506 hasSubpages( $contextTitle->getNamespace() )
1508 $hash = strpos( $target,
'#' );
1509 if ( $hash !==
false ) {
1510 $suffix = substr( $target, $hash );
1511 $target = substr( $target, 0, $hash );
1516 $target = trim( $target );
1517 $contextPrefixedText = MediaWikiServices::getInstance()->getTitleFormatter()->
1518 getPrefixedText( $contextTitle );
1519 # Look at the first character
1520 if ( $target !=
'' && $target[0] ===
'/' ) {
1521 # / at end means we don't want the slash to be shown
1523 $trailingSlashes = preg_match_all(
'%(/+)$%', $target, $m );
1524 if ( $trailingSlashes ) {
1525 $noslash = $target = substr( $target, 1, -strlen( $m[0][0] ) );
1527 $noslash = substr( $target, 1 );
1530 $ret = $contextPrefixedText .
'/' . trim( $noslash ) . $suffix;
1531 if ( $text ===
'' ) {
1532 $text = $target . $suffix;
1533 } #
this might be changed
for ugliness reasons
1535 # check for .. subpage backlinks
1537 $nodotdot = $target;
1538 while ( str_starts_with( $nodotdot,
'../' ) ) {
1540 $nodotdot = substr( $nodotdot, 3 );
1542 if ( $dotdotcount > 0 ) {
1543 $exploded = explode(
'/', $contextPrefixedText );
1544 if ( count( $exploded ) > $dotdotcount ) { # not allowed to go below top level page
1545 $ret = implode(
'/', array_slice( $exploded, 0, -$dotdotcount ) );
1546 # / at the end means don't show full path
1547 if ( substr( $nodotdot, -1, 1 ) ===
'/' ) {
1548 $nodotdot = rtrim( $nodotdot,
'/' );
1549 if ( $text ===
'' ) {
1550 $text = $nodotdot . $suffix;
1553 $nodotdot = trim( $nodotdot );
1554 if ( $nodotdot !=
'' ) {
1555 $ret .=
'/' . $nodotdot;
1586 $comment,
$title =
null, $local =
false, $wikiId =
null, $useParentheses =
true
1588 return MediaWikiServices::getInstance()->getCommentFormatter()
1589 ->formatBlock( $comment,
$title, $local, $wikiId, $useParentheses );
1611 $useParentheses =
true
1613 $authority = RequestContext::getMain()->getAuthority();
1614 $formatter = MediaWikiServices::getInstance()->getCommentFormatter();
1615 return $formatter->formatRevision( $revRecord, $authority, $local, $isPublic, $useParentheses );
1625 $stxt =
wfMessage(
'historyempty' )->escaped();
1627 $stxt =
wfMessage(
'nbytes' )->numParams( $size )->escaped();
1629 return "<span class=\"history-size mw-diff-bytes\" data-mw-bytes=\"$size\">$stxt</span>";
1650 return "</li>\n" . str_repeat(
"</ul>\n</li>\n", $level > 0 ? $level : 0 );
1664 public static function tocLine( $anchor, $tocline, $tocnumber, $level, $sectionIndex =
false ) {
1665 $classes =
"toclevel-$level";
1666 if ( $sectionIndex !==
false ) {
1667 $classes .=
" tocsection-$sectionIndex";
1672 return Html::openElement(
'li', [
'class' => $classes ] )
1673 . Html::rawElement(
'a',
1674 [
'href' =>
"#$anchor" ],
1675 Html::element(
'span', [
'class' =>
'tocnumber' ], $tocnumber )
1677 . Html::rawElement(
'span', [
'class' =>
'toctext' ], $tocline )
1701 $lang =
$lang ?? RequestContext::getMain()->getLanguage();
1705 return '<div id="toc" class="toc" role="navigation" aria-labelledby="mw-toc-heading">'
1706 . Html::element(
'input', [
1707 'type' =>
'checkbox',
1709 'id' =>
'toctogglecheckbox',
1710 'class' =>
'toctogglecheckbox',
1711 'style' =>
'display:none',
1713 . Html::openElement(
'div', [
1714 'class' =>
'toctitle',
1715 'lang' =>
$lang->getHtmlCode(),
1716 'dir' =>
$lang->getDir(),
1718 .
'<h2 id="mw-toc-heading">' .
$title .
'</h2>'
1719 .
'<span class="toctogglespan">'
1720 . Html::label(
'',
'toctogglecheckbox', [
1721 'class' =>
'toctogglelabel',
1726 .
"</ul>\n</div>\n";
1740 foreach ( $tree as $section ) {
1741 if ( $section[
'toclevel'] > $lastLevel ) {
1742 $toc .= self::tocIndent();
1743 } elseif ( $section[
'toclevel'] < $lastLevel ) {
1744 $toc .= self::tocUnindent(
1745 $lastLevel - $section[
'toclevel'] );
1747 $toc .= self::tocLineEnd();
1750 $toc .= self::tocLine( $section[
'anchor'],
1751 $section[
'line'], $section[
'number'],
1752 $section[
'toclevel'], $section[
'index'] );
1753 $lastLevel = $section[
'toclevel'];
1755 $toc .= self::tocLineEnd();
1756 return self::tocList( $toc,
$lang );
1776 $link, $fallbackAnchor =
false
1778 $anchorEscaped = htmlspecialchars( $anchor, ENT_COMPAT );
1780 if ( $fallbackAnchor !==
false && $fallbackAnchor !== $anchor ) {
1781 $fallbackAnchor = htmlspecialchars( $fallbackAnchor, ENT_COMPAT );
1782 $fallback =
"<span id=\"$fallbackAnchor\"></span>";
1784 return "<h$level$attribs"
1785 .
"$fallback<span class=\"mw-headline\" id=\"$anchorEscaped\">$html</span>"
1797 $regex = MediaWikiServices::getInstance()->getContentLanguage()->linkTrail();
1799 if ( $trail !==
'' && preg_match( $regex, $trail, $m ) ) {
1800 [ , $inside, $trail ] = $m;
1802 return [ $inside, $trail ];
1837 $options = [
'verify' ]
1839 if ( $context ===
null ) {
1840 $context = RequestContext::getMain();
1844 if ( in_array(
'verify', $options,
true ) ) {
1845 $editCount = self::getRollbackEditCount( $revRecord,
true );
1846 if ( $editCount ===
false ) {
1851 $inner = self::buildRollbackLink( $revRecord, $context, $editCount );
1855 if ( !Hooks::runner()->onLinkerGenerateRollbackLink(
1856 $revRecord, $context, $options, $inner ) ) {
1860 if ( !in_array(
'noBrackets', $options,
true ) ) {
1861 $inner = $context->msg(
'brackets' )->rawParams( $inner )->escaped();
1864 if ( MediaWikiServices::getInstance()->getUserOptionsLookup()
1865 ->getBoolOption( $context->getUser(),
'showrollbackconfirmation' )
1867 $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
1868 $stats->increment(
'rollbackconfirmation.event.load' );
1869 $context->getOutput()->addModules(
'mediawiki.misc-authed-curate' );
1872 return '<span class="mw-rollback-link">' . $inner .
'</span>';
1894 $showRollbackEditCount = MediaWikiServices::getInstance()->getMainConfig()
1895 ->get( MainConfigNames::ShowRollbackEditCount );
1897 if ( !is_int( $showRollbackEditCount ) || !$showRollbackEditCount > 0 ) {
1905 $revQuery = MediaWikiServices::getInstance()->getRevisionStore()->getQueryInfo();
1906 $res =
$dbr->newSelectQueryBuilder()
1907 ->select( [
'rev_user_text' =>
$revQuery[
'fields'][
'rev_user_text'],
'rev_deleted' ] )
1909 ->where( [
'rev_page' => $revRecord->
getPageId() ] )
1911 ->useIndex( [
'revision' =>
'rev_page_timestamp' ] )
1912 ->orderBy( [
'rev_timestamp',
'rev_id' ], SelectQueryBuilder::SORT_DESC )
1913 ->limit( $showRollbackEditCount + 1 )
1914 ->caller( __METHOD__ )
1917 $revUser = $revRecord->
getUser( RevisionRecord::RAW );
1918 $revUserText = $revUser ? $revUser->getName() :
'';
1922 foreach (
$res as $row ) {
1923 if ( $row->rev_user_text != $revUserText ) {
1925 ( $row->rev_deleted & RevisionRecord::DELETED_TEXT
1926 || $row->rev_deleted & RevisionRecord::DELETED_USER
1939 if ( $verify && $editCount <= $showRollbackEditCount && !$moreRevs ) {
1967 $config = MediaWikiServices::getInstance()->getMainConfig();
1968 $showRollbackEditCount = $config->get( MainConfigNames::ShowRollbackEditCount );
1969 $miserMode = $config->get( MainConfigNames::MiserMode );
1971 $disableRollbackEditCountSpecialPage = [
'Recentchanges',
'Watchlist' ];
1973 if ( $context ===
null ) {
1974 $context = RequestContext::getMain();
1978 $revUser = $revRecord->
getUser();
1979 $revUserText = $revUser ? $revUser->getName() :
'';
1982 'action' =>
'rollback',
1983 'from' => $revUserText,
1984 'token' => $context->getUser()->getEditToken(
'rollback' ),
1988 'data-mw' =>
'interface',
1989 'title' => $context->msg(
'tooltip-rollback' )->text()
1992 $options = [
'known',
'noclasses' ];
1994 if ( $context->getRequest()->getBool(
'bot' ) ) {
1996 $query[
'hidediff'] =
'1';
1997 $query[
'bot'] =
'1';
2001 foreach ( $disableRollbackEditCountSpecialPage as $specialPage ) {
2002 if ( $context->getTitle()->isSpecial( $specialPage ) ) {
2003 $showRollbackEditCount =
false;
2010 $msg = [
'rollbacklink' ];
2011 if ( is_int( $showRollbackEditCount ) && $showRollbackEditCount > 0 ) {
2012 if ( !is_numeric( $editCount ) ) {
2013 $editCount = self::getRollbackEditCount( $revRecord,
false );
2016 if ( $editCount > $showRollbackEditCount ) {
2017 $msg = [
'rollbacklinkcount-morethan',
Message::numParam( $showRollbackEditCount ) ];
2018 } elseif ( $editCount ) {
2023 $html = $context->msg( ...$msg )->parse();
2024 return self::link(
$title, $html, $attrs, $query, $options );
2037 if ( count( $hiddencats ) > 0 ) {
2038 # Construct the HTML
2039 $outText =
'<div class="mw-hiddenCategoriesExplanation">';
2040 $outText .=
wfMessage(
'hiddencategories' )->numParams( count( $hiddencats ) )->parseAsBlock();
2041 $outText .=
"</div><ul>\n";
2043 foreach ( $hiddencats as $titleObj ) {
2044 # If it's hidden, it must exist - no need to check with a LinkBatch
2046 . self::link( $titleObj,
null, [], [],
'known' )
2049 $outText .=
'</ul>';
2057 private static function getContextFromMain() {
2058 $context = RequestContext::getMain();
2080 public static function titleAttrib( $name, $options =
null, array $msgParams = [], $localizer =
null ) {
2081 if ( !$localizer ) {
2082 $localizer = self::getContextFromMain();
2084 $message = $localizer->msg(
"tooltip-$name", $msgParams );
2085 if ( $message->isDisabled() ) {
2088 $tooltip = $message->text();
2089 # Compatibility: formerly some tooltips had [alt-.] hardcoded
2090 $tooltip = preg_replace(
"/ ?\[alt-.\]$/",
'', $tooltip );
2093 $options = (array)$options;
2095 if ( in_array(
'nonexisting', $options ) ) {
2096 $tooltip = $localizer->msg(
'red-link-title', $tooltip ?:
'' )->text();
2098 if ( in_array(
'withaccess', $options ) ) {
2099 $accesskey = self::accesskey( $name, $localizer );
2100 if ( $accesskey !==
false ) {
2102 if ( $tooltip ===
false || $tooltip ===
'' ) {
2103 $tooltip = $localizer->msg(
'brackets', $accesskey )->text();
2105 $tooltip .= $localizer->msg(
'word-separator' )->text();
2106 $tooltip .= $localizer->msg(
'brackets', $accesskey )->text();
2128 public static function accesskey( $name, $localizer =
null ) {
2129 if ( !isset( self::$accesskeycache[$name] ) ) {
2130 if ( !$localizer ) {
2131 $localizer = self::getContextFromMain();
2133 $msg = $localizer->msg(
"accesskey-$name" );
2134 self::$accesskeycache[$name] = $msg->isDisabled() ? false : $msg->plain();
2136 return self::$accesskeycache[$name];
2158 $canHide = $performer->
isAllowed(
'deleterevision' );
2159 $canHideHistory = $performer->
isAllowed(
'deletedhistory' );
2160 if ( !$canHide && !( $revRecord->
getVisibility() && $canHideHistory ) ) {
2164 if ( !$revRecord->
userCan( RevisionRecord::DELETED_RESTRICTED, $performer ) ) {
2165 return self::revDeleteLinkDisabled( $canHide );
2167 $prefixedDbKey = MediaWikiServices::getInstance()->getTitleFormatter()->
2168 getPrefixedDBkey(
$title );
2169 if ( $revRecord->
getId() ) {
2173 'type' =>
'revision',
2174 'target' => $prefixedDbKey,
2175 'ids' => $revRecord->
getId()
2181 'type' =>
'archive',
2182 'target' => $prefixedDbKey,
2186 return self::revDeleteLink(
2188 $revRecord->
isDeleted( RevisionRecord::DELETED_RESTRICTED ),
2205 public static function revDeleteLink( $query = [], $restricted =
false, $delete =
true ) {
2207 $msgKey = $delete ?
'rev-delundel' :
'rev-showdeleted';
2208 $html =
wfMessage( $msgKey )->escaped();
2209 $tag = $restricted ?
'strong' :
'span';
2210 $link = self::link( $sp, $html, [], $query, [
'known',
'noclasses' ] );
2213 [
'class' =>
'mw-revdelundel-link' ],
2214 wfMessage(
'parentheses' )->rawParams( $link )->escaped()
2230 $msgKey = $delete ?
'rev-delundel' :
'rev-showdeleted';
2231 $html =
wfMessage( $msgKey )->escaped();
2232 $htmlParentheses =
wfMessage(
'parentheses' )->rawParams( $html )->escaped();
2233 return Xml::tags(
'span', [
'class' =>
'mw-revdelundel-link' ], $htmlParentheses );
2247 private static function updateWatchstarTooltipMessage(
2248 string &$tooltip, array &$msgParams, $config, $user, $relevantTitle
2250 if ( !$config || !$user || !$relevantTitle ) {
2251 $mainContext = self::getContextFromMain();
2253 $config = $mainContext->getConfig();
2256 $user = $mainContext->getUser();
2258 if ( !$relevantTitle ) {
2259 $relevantTitle = $mainContext->getSkin()->getRelevantTitle();
2263 $isWatchlistExpiryEnabled = $config->get( MainConfigNames::WatchlistExpiry );
2264 if ( !$isWatchlistExpiryEnabled || !$relevantTitle || !$relevantTitle->canExist() ) {
2268 $watchStore = MediaWikiServices::getInstance()->getWatchedItemStore();
2269 $watchedItem = $watchStore->getWatchedItem( $user, $relevantTitle );
2271 $diffInDays = $watchedItem->getExpiryInDays();
2273 if ( $diffInDays ) {
2274 $msgParams = [ $diffInDays ];
2276 $tooltip =
'ca-unwatch-expiring';
2278 $tooltip =
'ca-unwatch-expiring-hours';
2301 array $msgParams = [],
2306 $relevantTitle =
null
2308 $options = (array)$options;
2309 $options[] =
'withaccess';
2310 $tooltipTitle = $name;
2313 if ( !$localizer ) {
2314 $localizer = self::getContextFromMain();
2318 if ( $name ===
'ca-unwatch' ) {
2319 self::updateWatchstarTooltipMessage( $tooltipTitle, $msgParams, $config, $user, $relevantTitle );
2323 'title' => self::titleAttrib( $tooltipTitle, $options, $msgParams, $localizer ),
2324 'accesskey' => self::accesskey( $name, $localizer )
2326 if ( $attribs[
'title'] ===
false ) {
2327 unset( $attribs[
'title'] );
2329 if ( $attribs[
'accesskey'] ===
false ) {
2330 unset( $attribs[
'accesskey'] );
2342 public static function tooltip( $name, $options =
null ) {
2343 $tooltip = self::titleAttrib( $name, $options );
2344 if ( $tooltip ===
false ) {
2347 return Xml::expandAttributes( [
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfWarn( $msg, $callerOffset=1, $level=E_USER_NOTICE)
Send a warning either to the debug log or in a PHP error depending on $wgDevelopmentWarnings.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfExpandUrl( $url, $defaultProto=PROTO_CURRENT)
Expand a potentially local URL to a fully-qualified URL.
wfLogWarning( $msg, $callerOffset=1, $level=E_USER_WARNING)
Send a warning as a PHP error and the debug log.
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode $wgLang
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode $wgTitle
if(!defined('MW_SETUP_CALLBACK'))
The persistent session ID (if any) loaded at startup.
An IContextSource implementation which will inherit context from another source but allow individual ...
Marks HTML that shouldn't be escaped.
Base class for language-specific code.
Some internal bits split of from Skin.php.
static makeThumbLinkObj(LinkTarget $title, $file, $label='', $alt='', $align=null, $params=[], $framed=false, $manualthumb='')
Make HTML for a thumbnail including image, border and caption.
static accesskey( $name, $localizer=null)
Given the id of an interface element, constructs the appropriate accesskey attribute from the system ...
static makeMediaLinkFile(LinkTarget $title, $file, $html='')
Create a direct link to a given uploaded file.
static link( $target, $html=null, $customAttribs=[], $query=[], $options=[])
This function returns an HTML link to the given target.
static tocLine( $anchor, $tocline, $tocnumber, $level, $sectionIndex=false)
parameter level defines if we are on an indentation level
static userLink( $userId, $userName, $altUserName=false)
Make user link (or user contributions for unregistered users)
static expandLocalLinks(string $html)
Helper function to expand local links.
static makeBrokenImageLinkObj( $title, $label='', $query='', $unused1='', $unused2='', $time=false, array $handlerParams=[], bool $currentExists=false)
Make a "broken" link to an image.
static getRevisionDeletedClass(RevisionRecord $revisionRecord)
Returns css class of a deleted revision.
static specialLink( $name, $key='')
Make a link to a special page given its name and, optionally, a message key from the link text.
static getRollbackEditCount(RevisionRecord $revRecord, $verify)
This function will return the number of revisions which a rollback would revert and,...
static linkKnown( $target, $html=null, $customAttribs=[], $query=[], $options=[ 'known'])
Identical to link(), except $options defaults to 'known'.
static makeExternalImage( $url, $alt='')
Return the code for images which were added via external links, via Parser::maybeMakeExternalImage().
static revComment(RevisionRecord $revRecord, $local=false, $isPublic=false, $useParentheses=true)
Wrap and format the given revision's comment block, if the current user is allowed to view it.
static revUserLink(RevisionRecord $revRecord, $isPublic=false)
Generate a user link if the current user is allowed to view it.
static processResponsiveImages( $file, $thumb, $hp)
Process responsive images: add 1.5x and 2x subimages to the thumbnail, where applicable.
static blockLink( $userId, $userText)
static revDeleteLinkDisabled( $delete=true)
Creates a dead (show/hide) link for deleting revisions/log entries.
static normalizeSubpageLink( $contextTitle, $target, &$text)
const TOOL_LINKS_NOBLOCK
Flags for userToolLinks()
static getRevDeleteLink(Authority $performer, RevisionRecord $revRecord, LinkTarget $title)
Get a revision-deletion link, or disabled link, or nothing, depending on user permissions & the setti...
static makeSelfLinkObj( $nt, $html='', $query='', $trail='', $prefix='')
Make appropriate markup for a link to the current article.
static getUploadUrl( $destFile, $query='')
Get the URL to upload a certain file.
static makeImageLink(Parser $parser, LinkTarget $title, $file, $frameParams=[], $handlerParams=[], $time=false, $query='', $widthOption=null)
Given parameters derived from [[Image:Foo|options...]], generate the HTML that that syntax inserts in...
static tocIndent()
Add another level to the Table of Contents.
static makeThumbLink2(LinkTarget $title, $file, $frameParams=[], $handlerParams=[], $time=false, $query='', array $classes=[], ?Parser $parser=null)
static getInvalidTitleDescription(IContextSource $context, $namespace, $title)
Get a message saying that an invalid title was encountered.
static emailLink( $userId, $userText)
static generateRollback(RevisionRecord $revRecord, IContextSource $context=null, $options=[ 'verify'])
Generate a rollback link for a given revision.
static formatHiddenCategories( $hiddencats)
Returns HTML for the "hidden categories on this page" list.
static splitTrail( $trail)
Split a link trail, return the "inside" portion and the remainder of the trail as a two-element array...
static generateTOC( $tree, Language $lang=null)
Generate a table of contents from a section tree.
static titleAttrib( $name, $options=null, array $msgParams=[], $localizer=null)
Given the id of an interface element, constructs the appropriate title attribute from the system mess...
static formatRevisionSize( $size)
static commentBlock( $comment, $title=null, $local=false, $wikiId=null, $useParentheses=true)
Wrap a comment in standard punctuation and formatting if it's non-empty, otherwise return empty strin...
static tooltip( $name, $options=null)
Returns raw bits of HTML, use titleAttrib()
static userTalkLink( $userId, $userText)
static buildRollbackLink(RevisionRecord $revRecord, IContextSource $context=null, $editCount=false)
Build a raw rollback link, useful for collections of "tool" links.
static revUserTools(RevisionRecord $revRecord, $isPublic=false, $useParentheses=true)
Generate a user tool link cluster if the current user is allowed to view it.
static formatLinksInComment( $comment, $title=null, $local=false, $wikiId=null)
Formats wiki links and media links in text; all other wiki formatting is ignored.
static makeMediaLinkObj( $title, $html='', $time=false)
Create a direct link to a given uploaded file.
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
static userToolLinks( $userId, $userText, $redContribsWhenNoEdits=false, $flags=0, $edits=null, $useParentheses=true)
Generate standard user tool links (talk, contributions, block link, etc.)
static normaliseSpecialPage(LinkTarget $target)
static makeHeadline( $level, $attribs, $anchor, $html, $link, $fallbackAnchor=false)
Create a headline for content.
static tocUnindent( $level)
Finish one or more sublevels on the Table of Contents.
static tocList( $toc, Language $lang=null)
Wraps the TOC in a div with ARIA navigation role and provides the hide/collapse JavaScript.
static getImageLinkMTOParams( $frameParams, $query='', $parser=null)
Get the link parameters for MediaTransformOutput::toHtml() from given frame parameters supplied by th...
static revDeleteLink( $query=[], $restricted=false, $delete=true)
Creates a (show/hide) link for deleting revisions/log entries.
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null, $localizer=null, $user=null, $config=null, $relevantTitle=null)
Returns the attributes for the tooltip and access key.
static tocLineEnd()
End a Table Of Contents line.
static formatComment( $comment, $title=null, $local=false, $wikiId=null)
This function is called by all recent changes variants, by the page history, and by the user contribu...
static userToolLinksRedContribs( $userId, $userText, $edits=null, $useParentheses=true)
Alias for userToolLinks( $userId, $userText, true );.
A class containing constants representing the names of configuration variables.
PHP Parser - Processes wiki markup (which uses a more user-friendly syntax, such as "[[link]]" for ma...
getTargetLanguage()
Get the target language for the content being parsed.
getBadFileLookup()
Get the BadFileLookup instance that this Parser is using.
static getExternalLinkRel( $url=false, LinkTarget $title=null)
Get the rel attribute for a particular external link.
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,...
static newFromId( $id)
Static factory method for creation from a given user ID.
Representation of a pair of user and title for watchlist entries.
getExpiry(?int $style=TS_MW)
When the watched item will expire.
Interface for objects which can provide a MediaWiki context on request.
msg( $key,... $params)
This is the method for getting translated interface messages.
foreach( $mmfl['setupFiles'] as $fileName) if($queue) if(empty( $mmfl['quiet'])) $s
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
if(!isset( $args[0])) $lang