23use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
26use Wikimedia\WrappedString;
27use Wikimedia\WrappedStringList;
42 use ProtectedHookAccessorTrait;
52 protected $options = [];
60 public $stylename =
null;
67 $skinFactory = MediaWikiServices::getInstance()->getSkinFactory();
68 return $skinFactory->getSkinNames();
81 $allowedSkins = self::getSkinNames();
84 unset( $allowedSkins[
'fallback'] );
85 unset( $allowedSkins[
'apioutput'] );
88 unset( $allowedSkins[$skip] );
106 $skinNames = self::getSkinNames();
109 $skinNames = array_change_key_case( $skinNames, CASE_LOWER );
110 $key = strtolower( $key );
114 if ( $key ==
'' || $key ==
'default' ) {
120 if ( isset( $skinNames[$key] ) ) {
135 if ( isset( $skinNames[$key] ) ) {
137 } elseif ( isset( $skinNames[$defaultSkin] ) ) {
140 return $fallbackSkin;
153 if ( is_string( $options ) ) {
154 $this->skinname = $options;
155 } elseif ( $options ) {
156 $this->options = $options;
157 $name = $options[
'name'] ??
null;
160 $this->skinname = $name;
169 return $this->skinname;
203 'skin' => $this->options[
'styles'] ?? [],
210 'mediawiki.page.startup',
214 'mediawiki.page.ready',
219 'skin' => $this->options[
'scripts'] ?? [],
229 if ( strpos( $out->getHTML(),
'sortable' ) !==
false ) {
230 $modules[
'content'][] =
'jquery.tablesorter';
231 $modules[
'styles'][
'content'][] =
'jquery.tablesorter.styles';
235 if ( strpos( $out->getHTML(),
'mw-collapsible' ) !==
false ) {
236 $modules[
'content'][] =
'jquery.makeCollapsible';
237 $modules[
'styles'][
'content'][] =
'jquery.makeCollapsible.styles';
242 if ( strpos( $out->getHTML(),
'mw-ui-button' ) !==
false ) {
243 $modules[
'styles'][
'content'][] =
'mediawiki.ui.button';
246 if ( $out->isTOCEnabled() ) {
247 $modules[
'content'][] =
'mediawiki.toc';
248 $modules[
'styles'][
'content'][] =
'mediawiki.toc.styles';
251 $prefMgr = MediaWikiServices::getInstance()->getPermissionManager();
252 if ( $user->isLoggedIn()
253 && $prefMgr->userHasAllRights( $user,
'writeapi',
'viewmywatchlist',
'editmywatchlist' )
254 && $this->getRelevantTitle()->canExist()
256 $modules[
'watch'][] =
'mediawiki.page.watch.ajax';
259 if ( $user->getBoolOption(
'editsectiononrightclick' )
260 || ( $out->isArticle() && $user->getOption(
'editondblclick' ) )
262 $modules[
'user'][] =
'mediawiki.misc-authed-pref';
265 if ( $out->isSyndicated() ) {
266 $modules[
'styles'][
'syndicate'][] =
'mediawiki.feedlink';
280 if ( $user->isLoggedIn() ) {
281 $titles[] = $user->getUserPage();
282 $titles[] = $user->getTalkPage();
287 if (
$title->canExist() &&
$title->canHaveTalkPage() ) {
288 $namespaceInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
289 if (
$title->isTalkPage() ) {
290 $titles[] = $namespaceInfo->getSubjectPage(
$title );
292 $titles[] = $namespaceInfo->getTalkPage(
$title );
297 if ( $this->
getConfig()->
get(
'FooterLinkCacheExpiry' ) <= 0 ) {
298 $titles = array_merge(
308 $this->getHookRunner()->onSkinPreloadExistence( $titles, $this );
312 $lb->setCaller( __METHOD__ );
324 return $this->
getOutput()->getRevisionId();
334 return $this->
getOutput()->isRevisionCurrent();
343 $this->mRelevantTitle =
$t;
357 return $this->mRelevantTitle ?? $this->
getTitle();
366 $this->mRelevantUser = $u;
378 if ( isset( $this->mRelevantUser ) ) {
379 return $this->mRelevantUser;
383 $rootUser =
$title->getRootText();
390 $user->load( User::READ_NORMAL );
392 if ( $user->isLoggedIn() ) {
393 $this->mRelevantUser = $user;
397 return $this->mRelevantUser;
432 'ctype' =>
'text/css',
452 $numeric =
'ns-' .
$title->getNamespace();
455 if (
$title->isSpecialPage() ) {
456 $type =
'ns-special';
458 list( $canonicalName ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
459 resolveAlias(
$title->getDBkey() );
460 if ( $canonicalName ) {
461 $type .=
' ' . Sanitizer::escapeClass(
"mw-special-$canonicalName" );
463 $type .=
' mw-invalidspecialpage';
466 if (
$title->isTalkPage() ) {
469 $type =
'ns-subject';
473 ->quickUserCan(
'edit', $user,
$title )
475 $type .=
' mw-editable';
479 $name = Sanitizer::escapeClass(
'page-' .
$title->getPrefixedText() );
480 $root = Sanitizer::escapeClass(
'rootpage-' .
$title->getRootTitle()->getPrefixedText() );
482 return "$numeric $type $name $root";
492 'lang' =>
$lang->getHtmlCode(),
493 'dir' =>
$lang->getDir(),
494 'class' =>
'client-nojs',
512 $allCats = $out->getCategoryLinks();
514 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
516 if ( $allCats === [] ) {
524 $colon = $this->
msg(
'colon-separator' )->escaped();
526 if ( !empty( $allCats[
'normal'] ) ) {
527 $t = $embed . implode( $pop . $embed, $allCats[
'normal'] ) . $pop;
529 $msg = $this->
msg(
'pagecategories' )->numParams( count( $allCats[
'normal'] ) );
530 $linkPage = $this->
msg(
'pagecategorieslink' )->inContentLanguage()->text();
531 $pageCategoriesLinkTitle = Title::newFromText( $linkPage );
532 if ( $pageCategoriesLinkTitle ) {
533 $link = $linkRenderer->makeLink( $pageCategoriesLinkTitle, $msg->text() );
535 $link = $msg->escaped();
537 $s .=
'<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
538 $link . $colon .
'<ul>' .
$t .
'</ul></div>';
542 if ( isset( $allCats[
'hidden'] ) ) {
543 if ( $this->
getUser()->getBoolOption(
'showhiddencats' ) ) {
544 $class =
' mw-hidden-cats-user-shown';
546 $class =
' mw-hidden-cats-ns-shown';
548 $class =
' mw-hidden-cats-hidden';
551 $s .=
"<div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks$class\">" .
552 $this->
msg(
'hidden-categories' )->numParams( count( $allCats[
'hidden'] ) )->escaped() .
553 $colon .
'<ul>' . $embed . implode( $pop . $embed, $allCats[
'hidden'] ) . $pop .
'</ul>' .
557 # optional 'dmoz-like' category browser. Will be shown under the list
558 # of categories an article belong to
559 if ( $this->
getConfig()->
get(
'UseCategoryBrowser' ) ) {
560 $s .=
'<br /><hr />';
562 # get a big array of the parents tree
563 $parenttree =
$title->getParentCategoryTree();
564 # Skin object passed by reference cause it can not be
565 # accessed under the method subfunction drawCategoryBrowser
567 # Clean out bogus first entry and sort them
568 unset( $tempout[0] );
570 # Output one per line
571 $s .= implode(
"<br />\n", $tempout );
584 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
586 foreach ( $tree as $element => $parent ) {
587 if ( empty( $parent ) ) {
588 # element start a new list
591 # grab the others elements
595 # add our current element to the list
596 $eltitle = Title::newFromText( $element );
597 $return .= $linkRenderer->makeLink( $eltitle, $eltitle->getText() );
609 $allCats = $this->
getOutput()->getCategoryLinks();
610 $showHidden = $this->
getUser()->getBoolOption(
'showhiddencats' ) ||
613 $classes = [
'catlinks' ];
614 if ( empty( $allCats[
'normal'] ) && !( !empty( $allCats[
'hidden'] ) && $showHidden ) ) {
615 $classes[] =
'catlinks-allhidden';
618 return Html::rawElement(
620 [
'id' =>
'catlinks',
'class' => $classes,
'data-mw' =>
'interface' ],
642 if ( $this->getHookRunner()->onSkinAfterContent( $data, $this ) ) {
645 if ( trim( $data ) !=
'' ) {
649 $data =
"<div id='mw-data-after-content'>\n" .
654 wfDebug(
"Hook SkinAfterContent changed output processing." );
669 return MWDebug::getHTMLDebugLog();
681 $chunks = [ $this->
getOutput()->getBottomScripts() ];
686 $this->getHookRunner()->onSkinAfterBottomScripts( $this, $extraHtml );
687 if ( $extraHtml !==
'' ) {
688 $chunks[] = $extraHtml;
690 return WrappedString::join(
"\n", $chunks );
702 $oldid = $this->
getOutput()->getRevisionId();
704 $canonicalUrl =
$title->getCanonicalURL(
'oldid=' . $oldid );
705 $url = htmlspecialchars(
wfExpandIRI( $canonicalUrl ) );
711 return $this->
msg(
'retrievedfrom' )
712 ->rawParams(
'<a dir="ltr" href="' . $url .
'">' . $url .
'</a>' )
720 $action = $this->
getRequest()->getVal(
'action',
'view' );
723 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
724 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
726 if ( ( !
$title->exists() || $action ==
'history' ) &&
727 $permissionManager->quickUserCan(
'deletedhistory', $user,
$title )
732 if ( $permissionManager->quickUserCan(
'undelete', $user,
$title ) ) {
733 $msg =
'thisisdeleted';
735 $msg =
'viewdeleted';
738 $subtitle = $this->
msg( $msg )->rawParams(
739 $linkRenderer->makeKnownLink(
741 $this->msg(
'restorelink' )->numParams( $n )->text() )
747 if ( $action !==
'history' ) {
748 $links[] = $linkRenderer->makeKnownLink(
750 $this->
msg(
'viewpagelogs-lowercase' )->text(),
752 [
'page' =>
$title->getPrefixedText() ]
757 $this->getHookRunner()->onUndeletePageToolLinks(
762 . $this->
msg(
'word-separator' )->escaped()
763 . $this->
msg(
'parentheses' )
764 ->rawParams( $this->
getLanguage()->pipeList( $links ) )
768 return Html::rawElement(
'div', [
'class' =>
'mw-undelete-subtitle' ], $subtitle );
780 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
782 $title = $out->getTitle();
785 if ( !$this->getHookRunner()->onSkinSubPageSubtitle( $subpages, $this, $out ) ) {
790 $out->isArticle() && MediaWikiServices::getInstance()->getNamespaceInfo()->
791 hasSubpages(
$title->getNamespace() )
793 $ptext =
$title->getPrefixedText();
794 if ( strpos( $ptext,
'/' ) !==
false ) {
795 $links = explode(
'/', $ptext );
802 foreach ( $links as $link ) {
803 $growinglink .= $link;
805 $linkObj = Title::newFromText( $growinglink );
807 if ( is_object( $linkObj ) && $linkObj->isKnown() ) {
808 $getlink = $linkRenderer->makeKnownLink(
815 $subpages .=
$lang->getDirMarkEntity() . $this->
msg(
'pipe-separator' )->escaped();
817 $subpages .=
'< ';
820 $subpages .= $getlink;
838 return $searchPage->getLocalURL();
846 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
847 if (
$type ==
'detect' ) {
849 && !$this->
msg(
'history_copyright' )->inContentLanguage()->isDisabled()
857 if (
$type ==
'history' ) {
858 $msg =
'history_copyright';
865 if ( $config->get(
'RightsPage' ) ) {
866 $title = Title::newFromText( $config->get(
'RightsPage' ) );
867 $link = $linkRenderer->makeKnownLink(
870 } elseif ( $config->get(
'RightsUrl' ) ) {
872 } elseif ( $config->get(
'RightsText' ) ) {
873 $link = $config->get(
'RightsText' );
880 $this->getHookRunner()->onSkinCopyrightFooter( $this->
getTitle(),
$type, $msg, $link );
882 return $this->
msg( $msg )->rawParams( $link )->text();
892 $footerIcons = $config->get(
'FooterIcons' );
893 if ( $footerIcons[
'copyright'][
'copyright'] ) {
894 $out = $footerIcons[
'copyright'][
'copyright'];
895 } elseif ( $config->get(
'RightsIcon' ) ) {
896 $icon = htmlspecialchars( $config->get(
'RightsIcon' ) );
897 $url = $config->get(
'RightsUrl' );
900 $out .=
'<a href="' . htmlspecialchars( $url ) .
'">';
903 $text = htmlspecialchars( $config->get(
'RightsText' ) );
904 $out .=
"<img src=\"$icon\" alt=\"$text\" width=\"88\" height=\"31\" />";
919 $resourceBasePath = $this->
getConfig()->get(
'ResourceBasePath' );
920 $url1 = htmlspecialchars(
921 "$resourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
923 $url1_5 = htmlspecialchars(
924 "$resourceBasePath/resources/assets/poweredby_mediawiki_132x47.png"
926 $url2 = htmlspecialchars(
927 "$resourceBasePath/resources/assets/poweredby_mediawiki_176x62.png"
929 $text =
'<a href="https://www.mediawiki.org/"><img src="' . $url1
930 .
'" srcset="' . $url1_5 .
' 1.5x, ' . $url2 .
' 2x" '
931 .
'height="31" width="88" alt="Powered by MediaWiki" loading="lazy" /></a>';
932 $this->getHookRunner()->onSkinGetPoweredBy( $text, $this );
942 $timestamp = $this->
getOutput()->getRevisionTimestamp();
946 # No cached timestamp, load it from the database
947 if ( $timestamp ===
null ) {
948 $timestamp = MediaWikiServices::getInstance()
949 ->getRevisionLookup()
954 $d = $language->userDate( $timestamp, $user );
955 $t = $language->userTime( $timestamp, $user );
956 $s =
' ' . $this->
msg(
'lastmodifiedat', $d,
$t )->parse();
961 if ( MediaWikiServices::getInstance()->getDBLoadBalancer()->getLaggedReplicaMode() ) {
962 $s .=
' <strong>' . $this->
msg(
'laggedreplicamode' )->parse() .
'</strong>';
973 if ( $align !=
'' ) {
974 $a =
" style='float: {$align};'";
979 $mp = $this->
msg(
'mainpage' )->escaped();
980 $mptitle = Title::newMainPage();
981 $url = ( is_object( $mptitle ) ? htmlspecialchars( $mptitle->getLocalURL() ) :
'' );
984 return "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
996 if ( is_string( $icon ) ) {
999 $url = $icon[
'url'] ??
null;
1000 unset( $icon[
'url'] );
1001 if ( isset( $icon[
'src'] ) && $withImage ===
'withImage' ) {
1003 $icon[
'loading'] =
'lazy';
1005 $html = Html::element(
'img', $icon );
1007 $html = htmlspecialchars( $icon[
'alt'] ??
'' );
1010 $html = Html::rawElement(
'a',
1011 [
'href' => $url,
'target' => $this->
getConfig()->
get(
'ExternalLinkTarget' ) ],
1023 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1024 $s = $linkRenderer->makeKnownLink(
1025 Title::newMainPage(),
1026 $this->
msg(
'mainpage' )->text()
1040 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1045 return $linkRenderer->makeKnownLink(
1047 $this->
msg( $desc )->text()
1058 if ( $this->
msg( $desc )->inContentLanguage()->isDisabled() ) {
1065 $title = Title::newFromText( $this->
msg( $page )->inContentLanguage()->text() );
1077 $callback =
function () {
1085 $services = MediaWikiServices::getInstance();
1086 $msgCache = $services->getMessageCache();
1087 $wanCache = $services->getMainWANObjectCache();
1090 return ( $config->get(
'FooterLinkCacheExpiry' ) > 0 )
1091 ? $wanCache->getWithSetCallback(
1092 $wanCache->makeKey(
'footer-links' ),
1093 $config->get(
'FooterLinkCacheExpiry' ),
1099 $msgCache->getCheckKey( $this->getLanguage()->getCode() )
1112 return $this->
footerLink(
'privacy',
'privacypage' );
1120 return $this->
footerLink(
'aboutsite',
'aboutpage' );
1128 return $this->
footerLink(
'disclaimers',
'disclaimerpage' );
1139 $options = [
'action' =>
'edit' ];
1142 if ( !$out->isRevisionCurrent() ) {
1143 $options[
'oldid'] = intval( $out->getRevisionId() );
1154 if ( $id instanceof
User ) {
1160 # The sending user must have a confirmed email address and the receiving
1161 # user must accept emails from the sender.
1162 return $this->
getUser()->canSendEmail()
1178 if ( $this->stylename ===
null ) {
1179 $class = static::class;
1180 throw new MWException(
"$class::\$stylename must be set to use getSkinStylePath()" );
1183 return $this->
getConfig()->get(
'StylePath' ) .
"/{$this->stylename}/$name";
1193 $title = Title::newMainPage();
1194 self::checkTitle(
$title,
'' );
1196 return $title->getLinkURL( $urlaction );
1212 if ( $proto ===
null ) {
1213 return $title->getLocalURL( $urlaction );
1215 return $title->getFullURL( $urlaction,
false, $proto );
1227 return $title->getLocalURL( $urlaction );
1238 $title = Title::newFromText(
wfMessage( $name )->inContentLanguage()->text() );
1239 self::checkTitle(
$title, $name );
1240 return $title->getLocalURL( $urlaction );
1248 public static function makeUrl( $name, $urlaction =
'' ) {
1249 $title = Title::newFromText( $name );
1250 self::checkTitle(
$title, $name );
1252 return $title->getLocalURL( $urlaction );
1265 return self::makeUrl( $name );
1279 $title = Title::makeTitleSafe( $namespace, $name );
1280 self::checkTitle(
$title, $name );
1282 return $title->getLocalURL( $urlaction );
1292 $title = Title::newFromText( $name );
1293 self::checkTitle(
$title, $name );
1296 'href' =>
$title->getLocalURL( $urlaction ),
1297 'exists' =>
$title->isKnown(),
1308 $title = Title::newFromText( $name );
1309 self::checkTitle(
$title, $name );
1312 'href' =>
$title->getLocalURL( $urlaction ),
1324 if ( !is_object(
$title ) ) {
1325 $title = Title::newFromText( $name );
1326 if ( !is_object(
$title ) ) {
1327 $title = Title::newFromText(
'--error: link target missing--' );
1341 $map = $this->
getConfig()->get(
'InterlanguageLinkCodeMap' );
1342 return $map[ $code ] ?? $code;
1354 if ( $this->
getConfig()->
get(
'HideInterlanguageLinks' ) ) {
1357 $hookContainer = MediaWikiServices::getInstance()->getHookContainer();
1360 $languageLinks = [];
1361 $langNameUtils = MediaWikiServices::getInstance()->getLanguageNameUtils();
1363 foreach ( $this->
getOutput()->getLanguageLinks() as $languageLinkText ) {
1364 $class =
'interlanguage-link interwiki-' . explode(
':', $languageLinkText, 2 )[0];
1366 $languageLinkTitle = Title::newFromText( $languageLinkText );
1367 if ( !$languageLinkTitle ) {
1373 $ilLangName = $langNameUtils->getLanguageName( $ilInterwikiCode );
1375 if ( strval( $ilLangName ) ===
'' ) {
1376 $ilDisplayTextMsg = $this->
msg(
"interlanguage-link-$ilInterwikiCode" );
1377 if ( !$ilDisplayTextMsg->isDisabled() ) {
1379 $ilLangName = $ilDisplayTextMsg->text();
1382 $ilLangName = $languageLinkText;
1386 $ilLangName = $this->
getLanguage()->ucfirst( $ilLangName );
1391 $ilLangLocalName = $langNameUtils->getLanguageName(
1393 $userLang->getCode()
1396 $languageLinkTitleText = $languageLinkTitle->getText();
1397 if ( $ilLangLocalName ===
'' ) {
1398 $ilFriendlySiteName = $this->
msg(
"interlanguage-link-sitename-$ilInterwikiCode" );
1399 if ( !$ilFriendlySiteName->isDisabled() ) {
1400 if ( $languageLinkTitleText ===
'' ) {
1401 $ilTitle = $this->
msg(
1402 'interlanguage-link-title-nonlangonly',
1403 $ilFriendlySiteName->text()
1406 $ilTitle = $this->
msg(
1407 'interlanguage-link-title-nonlang',
1408 $languageLinkTitleText,
1409 $ilFriendlySiteName->text()
1416 $ilTitle = $languageLinkTitle->getInterwiki() .
1417 ":$languageLinkTitleText";
1419 } elseif ( $languageLinkTitleText ===
'' ) {
1420 $ilTitle = $this->
msg(
1421 'interlanguage-link-title-langonly',
1425 $ilTitle = $this->
msg(
1426 'interlanguage-link-title',
1427 $languageLinkTitleText,
1432 $ilInterwikiCodeBCP47 = LanguageCode::bcp47( $ilInterwikiCode );
1434 'href' => $languageLinkTitle->getFullURL(),
1435 'text' => $ilLangName,
1436 'title' => $ilTitle,
1438 'link-class' =>
'interlanguage-link-target',
1439 'lang' => $ilInterwikiCodeBCP47,
1440 'hreflang' => $ilInterwikiCodeBCP47,
1442 $hookContainer->run(
1443 'SkinTemplateGetLanguageLink',
1447 $languageLinks[] = $languageLink;
1450 return $languageLinks;
1463 $thispage =
$title->getPrefixedDBkey();
1464 $uploadNavigationUrl = $this->
getConfig()->get(
'UploadNavigationUrl' );
1467 $nav_urls[
'mainpage'] = [
'href' => self::makeMainPageUrl() ];
1468 if ( $uploadNavigationUrl ) {
1469 $nav_urls[
'upload'] = [
'href' => $uploadNavigationUrl ];
1470 } elseif ( UploadBase::isEnabled() && UploadBase::isAllowed( $this->
getUser() ) ===
true ) {
1471 $nav_urls[
'upload'] = [
'href' => self::makeSpecialUrl(
'Upload' ) ];
1473 $nav_urls[
'upload'] =
false;
1475 $nav_urls[
'specialpages'] = [
'href' => self::makeSpecialUrl(
'Specialpages' ) ];
1477 $nav_urls[
'print'] =
false;
1478 $nav_urls[
'permalink'] =
false;
1479 $nav_urls[
'info'] =
false;
1480 $nav_urls[
'whatlinkshere'] =
false;
1481 $nav_urls[
'recentchangeslinked'] =
false;
1482 $nav_urls[
'contributions'] =
false;
1483 $nav_urls[
'log'] =
false;
1484 $nav_urls[
'blockip'] =
false;
1485 $nav_urls[
'mute'] =
false;
1486 $nav_urls[
'emailuser'] =
false;
1487 $nav_urls[
'userrights'] =
false;
1491 if ( !$out->isPrintable() && ( $out->isArticle() ||
$title->isSpecialPage() ) ) {
1492 $nav_urls[
'print'] = [
1493 'text' => $this->
msg(
'printableversion' )->text(),
1494 'href' =>
'javascript:print();'
1498 if ( $out->isArticle() ) {
1500 $revid = $out->getRevisionId();
1502 $nav_urls[
'permalink'] = [
1503 'text' => $this->
msg(
'permalink' )->text(),
1504 'href' =>
$title->getLocalURL(
"oldid=$revid" )
1509 if ( $out->isArticleRelated() ) {
1510 $nav_urls[
'whatlinkshere'] = [
1514 $nav_urls[
'info'] = [
1515 'text' => $this->
msg(
'pageinfo-toolboxlink' )->text(),
1516 'href' =>
$title->getLocalURL(
"action=info" )
1520 $nav_urls[
'recentchangeslinked'] = [
1527 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
1534 if ( $user && $user->isRegistered() && $user->isHidden() &&
1535 !$permissionManager->userHasRight( $this->getUser(),
'hideuser' )
1541 $rootUser = $user->getName();
1543 $nav_urls[
'contributions'] = [
1544 'text' => $this->
msg(
'contributions', $rootUser )->text(),
1545 'href' => self::makeSpecialUrlSubpage(
'Contributions', $rootUser ),
1546 'tooltip-params' => [ $rootUser ],
1549 $nav_urls[
'log'] = [
1550 'href' => self::makeSpecialUrlSubpage(
'Log', $rootUser )
1553 if ( $permissionManager->userHasRight( $this->getUser(),
'block' ) ) {
1554 $nav_urls[
'blockip'] = [
1555 'text' => $this->
msg(
'blockip', $rootUser )->text(),
1556 'href' => self::makeSpecialUrlSubpage(
'Block', $rootUser )
1561 $nav_urls[
'emailuser'] = [
1562 'text' => $this->
msg(
'tool-link-emailuser', $rootUser )->text(),
1563 'href' => self::makeSpecialUrlSubpage(
'Emailuser', $rootUser ),
1564 'tooltip-params' => [ $rootUser ],
1568 if ( !$user->isAnon() ) {
1569 if ( $this->
getUser()->isRegistered() && $this->
getConfig()->
get(
'EnableSpecialMute' ) ) {
1570 $nav_urls[
'mute'] = [
1571 'text' => $this->
msg(
'mute-preferences' )->text(),
1572 'href' => self::makeSpecialUrlSubpage(
'Mute', $rootUser )
1578 $canChange = $sur->userCanChangeRights( $user );
1579 $nav_urls[
'userrights'] = [
1580 'text' => $this->
msg(
1581 $canChange ?
'tool-link-userrights' :
'tool-link-userrights-readonly',
1584 'href' => self::makeSpecialUrlSubpage(
'Userrights', $rootUser )
1600 if ( $out->isSyndicated() ) {
1601 foreach ( $out->getSyndicationLinks() as $format => $link ) {
1604 'text' => $this->
msg(
"feed-$format" )->text(),
1638 $services = MediaWikiServices::getInstance();
1639 $callback =
function ( $old =
null, &$ttl = null ) {
1642 $this->getHookRunner()->onSkinBuildSidebar( $this, $bar );
1643 $msgCache = MediaWikiServices::getInstance()->getMessageCache();
1644 if ( $msgCache->isDisabled() ) {
1645 $ttl = WANObjectCache::TTL_UNCACHEABLE;
1651 $msgCache = $services->getMessageCache();
1652 $wanCache = $services->getMainWANObjectCache();
1656 $sidebar = $config->get(
'EnableSidebarCache' )
1657 ? $wanCache->getWithSetCallback(
1658 $wanCache->makeKey(
'sidebar', $languageCode ),
1659 $config->get(
'SidebarCacheExpiry' ),
1665 $msgCache->getCheckKey( $languageCode )
1678 $this->getHookRunner()->onSidebarBeforeOutput( $this, $sidebar );
1704 $lines = explode(
"\n", $text );
1708 $messageTitle = $config->get(
'EnableSidebarCache' )
1709 ? Title::newMainPage() : $this->
getTitle();
1710 $messageCache = MediaWikiServices::getInstance()->getMessageCache();
1713 if ( strpos(
$line,
'*' ) !== 0 ) {
1718 if ( strpos(
$line,
'**' ) !== 0 ) {
1719 $heading = trim(
$line,
'* ' );
1720 if ( !array_key_exists( $heading, $bar ) ) {
1721 $bar[$heading] = [];
1726 if ( strpos(
$line,
'|' ) !==
false ) {
1727 $line = $messageCache->transform(
$line,
false,
null, $messageTitle );
1728 $line = array_map(
'trim', explode(
'|',
$line, 2 ) );
1729 if ( count(
$line ) !== 2 ) {
1737 $msgLink = $this->
msg(
$line[0] )->title( $messageTitle )->inContentLanguage();
1738 if ( $msgLink->exists() ) {
1739 $link = $msgLink->text();
1740 if ( $link ==
'-' ) {
1746 $msgText = $this->
msg(
$line[1] )->title( $messageTitle );
1747 if ( $msgText->exists() ) {
1748 $text = $msgText->text();
1757 if ( $config->get(
'NoFollowLinks' ) &&
1760 $extraAttribs[
'rel'] =
'nofollow';
1763 if ( $config->get(
'ExternalLinkTarget' ) ) {
1764 $extraAttribs[
'target'] = $config->get(
'ExternalLinkTarget' );
1767 $title = Title::newFromText( $link );
1771 $href =
$title->getLinkURL();
1773 $href =
'INVALID-TITLE';
1777 $bar[$heading][] = array_merge( [
1780 'id' => Sanitizer::escapeIdForAttribute(
'n-' . strtr(
$line[1],
' ',
'-' ) ),
1798 $newMessagesAlert =
'';
1800 $services = MediaWikiServices::getInstance();
1801 $linkRenderer = $services->getLinkRenderer();
1802 $userHasNewMessages = $services->getTalkPageNotificationManager()
1803 ->userHasNewMessages( $user );
1804 $timestamp = $services->getTalkPageNotificationManager()
1805 ->getLatestSeenMessageTimestamp( $user );
1806 $newtalks = !$userHasNewMessages ? [] : [
1809 'wiki' => WikiMap::getCurrentWikiId(),
1810 'link' => $user->getTalkPage()->getLocalURL(),
1811 'rev' => $timestamp ? $services->getRevisionLookup()
1812 ->getRevisionByTimestamp( $user->getTalkPage(), $timestamp ) : null
1818 if ( !$this->getHookRunner()->onGetNewMessagesAlert(
1819 $newMessagesAlert, $newtalks, $user, $out )
1823 if ( $newMessagesAlert ) {
1824 return $newMessagesAlert;
1827 if ( $newtalks !== [] ) {
1828 $uTalkTitle = $user->getTalkPage();
1829 $lastSeenRev = $newtalks[0][
'rev'];
1831 if ( $lastSeenRev !==
null ) {
1833 $revStore = $services->getRevisionStore();
1834 $latestRev =
$revStore->getRevisionByTitle(
1837 RevisionLookup::READ_NORMAL
1839 if ( $latestRev !==
null ) {
1841 $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
1842 $numAuthors =
$revStore->countAuthorsBetween(
1843 $uTalkTitle->getArticleID(),
1855 $plural = $plural ? 999 : 1;
1859 $newMessagesLink = $linkRenderer->makeKnownLink(
1861 $this->
msg(
'newmessageslinkplural' )->params( $plural )->text(),
1863 $uTalkTitle->isRedirect() ? [
'redirect' =>
'no' ] : []
1866 $newMessagesDiffLink = $linkRenderer->makeKnownLink(
1868 $this->
msg(
'newmessagesdifflinkplural' )->params( $plural )->text(),
1870 $lastSeenRev !==
null
1871 ? [
'oldid' => $lastSeenRev->getId(),
'diff' =>
'cur' ]
1872 : [
'diff' =>
'cur' ]
1875 if ( $numAuthors >= 1 && $numAuthors <= 10 ) {
1876 $newMessagesAlert = $this->
msg(
1877 'youhavenewmessagesfromusers',
1879 $newMessagesDiffLink
1880 )->numParams( $numAuthors, $plural );
1883 $newMessagesAlert = $this->
msg(
1884 $numAuthors > 10 ?
'youhavenewmessagesmanyusers' :
'youhavenewmessages',
1886 $newMessagesDiffLink
1887 )->numParams( $plural );
1889 $newMessagesAlert = $newMessagesAlert->text();
1891 $out->setCdnMaxage( 0 );
1894 return $newMessagesAlert;
1907 if ( $name ===
'default' ) {
1909 $notice = $config->get(
'SiteNotice' );
1910 if ( empty( $notice ) ) {
1914 $msg = $this->
msg( $name )->inContentLanguage();
1915 if ( $msg->isBlank() ) {
1917 } elseif ( $msg->isDisabled() ) {
1920 $notice = $msg->plain();
1923 $services = MediaWikiServices::getInstance();
1924 $cache = $services->getMainWANObjectCache();
1925 $parsed =
$cache->getWithSetCallback(
1928 $cache->makeKey( $name, $config->get(
'RenderHashAppend' ), md5( $notice ) ),
1931 function () use ( $notice ) {
1932 return $this->
getOutput()->parseAsInterface( $notice );
1936 $contLang = $services->getContentLanguage();
1937 return Html::rawElement(
1940 'id' =>
'localNotice',
1941 'lang' => $contLang->getHtmlCode(),
1942 'dir' => $contLang->getDir()
1956 if ( $this->getHookRunner()->onSiteNoticeBefore( $siteNotice, $this ) ) {
1957 if ( $this->
getUser()->isLoggedIn() ) {
1961 if ( $anonNotice ===
false ) {
1964 $siteNotice = $anonNotice;
1967 if ( $siteNotice ===
false ) {
1972 $this->getHookRunner()->onSiteNoticeAfter( $siteNotice, $this );
1994 if ( $tooltip !==
null ) {
1995 $attribs[
'title'] = $this->
msg(
'editsectionhint' )->rawParams( $tooltip )
1996 ->inLanguage(
$lang )->text();
2001 'text' => $this->
msg(
'editsection' )->inLanguage(
$lang )->text(),
2002 'targetTitle' => $nt,
2003 'attribs' => $attribs,
2004 'query' => [
'action' =>
'edit',
'section' => $section ]
2008 $this->getHookRunner()->onSkinEditSectionLinks( $this, $nt, $section, $tooltip, $links,
$lang );
2010 $result =
'<span class="mw-editsection"><span class="mw-editsection-bracket">[</span>';
2012 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
2014 foreach ( $links as $k => $linkDetails ) {
2015 $linksHtml[] = $linkRenderer->makeKnownLink(
2016 $linkDetails[
'targetTitle'],
2017 $linkDetails[
'text'],
2018 $linkDetails[
'attribs'],
2019 $linkDetails[
'query']
2024 '<span class="mw-editsection-divider">'
2025 . $this->
msg(
'pipe-separator' )->inLanguage(
$lang )->escaped()
2030 $result .=
'<span class="mw-editsection-bracket">]</span></span>';
2045 if ( $navUrls[
'whatlinkshere'] ??
null ) {
2046 $toolbox[
'whatlinkshere'] = $navUrls[
'whatlinkshere'];
2047 $toolbox[
'whatlinkshere'][
'id'] =
't-whatlinkshere';
2049 if ( $navUrls[
'recentchangeslinked'] ??
null ) {
2050 $toolbox[
'recentchangeslinked'] = $navUrls[
'recentchangeslinked'];
2051 $toolbox[
'recentchangeslinked'][
'msg'] =
'recentchangeslinked-toolbox';
2052 $toolbox[
'recentchangeslinked'][
'id'] =
't-recentchangeslinked';
2053 $toolbox[
'recentchangeslinked'][
'rel'] =
'nofollow';
2056 $toolbox[
'feeds'][
'id'] =
'feedlinks';
2057 $toolbox[
'feeds'][
'links'] = [];
2058 foreach ( $feedUrls as $key => $feed ) {
2059 $toolbox[
'feeds'][
'links'][$key] = $feed;
2060 $toolbox[
'feeds'][
'links'][$key][
'id'] =
"feed-$key";
2061 $toolbox[
'feeds'][
'links'][$key][
'rel'] =
'alternate';
2062 $toolbox[
'feeds'][
'links'][$key][
'type'] =
"application/{$key}+xml";
2063 $toolbox[
'feeds'][
'links'][$key][
'class'] =
'feedlink';
2066 foreach ( [
'contributions',
'log',
'blockip',
'emailuser',
'mute',
2067 'userrights',
'upload',
'specialpages' ] as $special
2069 if ( $navUrls[$special] ??
null ) {
2070 $toolbox[$special] = $navUrls[$special];
2071 $toolbox[$special][
'id'] =
"t-$special";
2074 if ( $navUrls[
'print'] ??
null ) {
2075 $toolbox[
'print'] = $navUrls[
'print'];
2076 $toolbox[
'print'][
'id'] =
't-print';
2077 $toolbox[
'print'][
'rel'] =
'alternate';
2078 $toolbox[
'print'][
'msg'] =
'printableversion';
2080 if ( $navUrls[
'permalink'] ??
null ) {
2081 $toolbox[
'permalink'] = $navUrls[
'permalink'];
2082 $toolbox[
'permalink'][
'id'] =
't-permalink';
2084 if ( $navUrls[
'info'] ??
null ) {
2085 $toolbox[
'info'] = $navUrls[
'info'];
2086 $toolbox[
'info'][
'id'] =
't-info';
2109 $out =
"<div class=\"mw-indicators mw-body-content\">\n";
2111 $out .= Html::rawElement(
2114 'id' => $indicatorData[
'id'],
2115 'class' => $indicatorData[
'class']
2117 $indicatorData[
'html']
2131 $indicatorData = [];
2132 foreach ( $indicators as $id =>
$content ) {
2133 $indicatorData[] = [
2134 'id' => Sanitizer::escapeIdForAttribute(
"mw-indicator-$id" ),
2135 'class' =>
'mw-indicator',
2139 return $indicatorData;
2155 $personal_tools = [];
2156 foreach ( $urls as $key => $plink ) {
2157 # The class on a personal_urls item is meant to go on the <a> instead
2158 # of the <li> so we have to use a single item "links" array instead
2159 # of using most of the personal_url's keys directly.
2162 [
'single-id' =>
"pt-$key" ],
2166 if ( isset( $plink[
'active'] ) ) {
2167 $ptool[
'active'] = $plink[
'active'];
2178 if ( isset( $plink[$k] ) ) {
2179 $ptool[
'links'][0][$k] = $plink[$k];
2182 $personal_tools[$key] = $ptool;
2184 return $personal_tools;
2240 final public function makeLink( $key, $item, $options = [] ) {
2241 $text = $item[
'text'] ?? $this->
msg( $item[
'msg'] ?? $key )->text();
2243 $html = htmlspecialchars( $text );
2245 if ( isset( $options[
'text-wrapper'] ) ) {
2246 $wrapper = $options[
'text-wrapper'];
2247 if ( isset( $wrapper[
'tag'] ) ) {
2248 $wrapper = [ $wrapper ];
2250 while ( count( $wrapper ) > 0 ) {
2251 $element = array_pop( $wrapper );
2253 $html = Html::rawElement( $element[
'tag'], $element[
'attributes'] ??
null, $html );
2257 if ( isset( $item[
'href'] ) || isset( $options[
'link-fallback'] ) ) {
2259 foreach ( [
'single-id',
'text',
'msg',
'tooltiponly',
'context',
'primary',
2260 'tooltip-params',
'exists' ] as $k ) {
2261 unset( $attrs[$k] );
2264 if ( isset( $attrs[
'data'] ) ) {
2265 foreach ( $attrs[
'data'] as $key => $value ) {
2266 $attrs[
'data-' . $key ] = $value;
2268 unset( $attrs[
'data' ] );
2271 if ( isset( $item[
'id'] ) && !isset( $item[
'single-id'] ) ) {
2272 $item[
'single-id'] = $item[
'id'];
2275 $tooltipParams = [];
2276 if ( isset( $item[
'tooltip-params'] ) ) {
2277 $tooltipParams = $item[
'tooltip-params'];
2280 if ( isset( $item[
'single-id'] ) ) {
2281 $tooltipOption = isset( $item[
'exists'] ) && $item[
'exists'] ===
false ?
'nonexisting' :
null;
2283 if ( isset( $item[
'tooltiponly'] ) && $item[
'tooltiponly'] ) {
2285 if (
$title !==
false ) {
2286 $attrs[
'title'] =
$title;
2294 if ( isset( $tip[
'title'] ) && $tip[
'title'] !==
false ) {
2295 $attrs[
'title'] = $tip[
'title'];
2297 if ( isset( $tip[
'accesskey'] ) && $tip[
'accesskey'] !==
false ) {
2298 $attrs[
'accesskey'] = $tip[
'accesskey'];
2302 if ( isset( $options[
'link-class'] ) ) {
2303 if ( isset( $attrs[
'class'] ) ) {
2304 $attrs[
'class'] .=
" {$options['link-class']}";
2306 $attrs[
'class'] = $options[
'link-class'];
2309 $html = Html::rawElement( isset( $attrs[
'href'] )
2311 : $options[
'link-fallback'], $attrs, $html );
2352 unset( $item[
'redundant'] );
2354 if ( isset( $item[
'links'] ) ) {
2356 foreach ( $item[
'links'] as $linkKey => $link ) {
2357 $links[] = $this->
makeLink( $linkKey, $link, $options );
2359 $html = implode(
' ', $links );
2363 foreach ( [
'id',
'class',
'active',
'tag',
'itemtitle' ] as $k ) {
2366 if ( isset( $item[
'id'] ) && !isset( $item[
'single-id'] ) ) {
2370 $link[
'single-id'] = $item[
'id'];
2372 if ( isset( $link[
'link-class'] ) ) {
2375 $link[
'class'] = $link[
'link-class'];
2376 unset( $link[
'link-class'] );
2378 $html = $this->
makeLink( $key, $link, $options );
2382 foreach ( [
'id',
'class' ] as $attr ) {
2383 if ( isset( $item[$attr] ) ) {
2384 $attrs[$attr] = $item[$attr];
2387 if ( isset( $item[
'active'] ) && $item[
'active'] ) {
2388 if ( !isset( $attrs[
'class'] ) ) {
2389 $attrs[
'class'] =
'';
2391 $attrs[
'class'] .=
' active';
2392 $attrs[
'class'] = trim( $attrs[
'class'] );
2394 if ( isset( $item[
'itemtitle'] ) ) {
2395 $attrs[
'title'] = $item[
'itemtitle'];
2397 return Html::rawElement( $options[
'tag'] ??
'li', $attrs, $html );
2410 'placeholder' => $this->
msg(
'searchsuggest-search' )->text(),
2413 return Html::element(
'input', $realAttrs );
2430 'value' => $this->
msg( $mode ==
'go' ?
'searcharticle' :
'searchbutton' )->text(),
2432 $realAttrs = array_merge(
2437 return Html::element(
'input', $realAttrs );
2443 $buttonAttrs = array_merge(
2448 unset( $buttonAttrs[
'src'] );
2449 unset( $buttonAttrs[
'alt'] );
2450 unset( $buttonAttrs[
'width'] );
2451 unset( $buttonAttrs[
'height'] );
2453 'src' => $attrs[
'src'],
2454 'alt' => $attrs[
'alt'] ?? $this->
msg(
'searchbutton' )->text(),
2455 'width' => $attrs[
'width'] ??
null,
2456 'height' => $attrs[
'height'] ??
null,
2458 return Html::rawElement(
'button', $buttonAttrs, Html::element(
'img', $imgAttrs ) );
2460 throw new MWException(
'Unknown mode passed to BaseTemplate::makeSearchButton' );
2477 $this->getHookRunner()->onSkinAfterPortlet( $this, $name, $html );
2494 $out = $this->getOutput();
2495 $title = $out->getTitle();
2496 $titleExists =
$title->exists();
2497 $config = $this->getConfig();
2498 $maxCredits = $config->get(
'MaxCredits' );
2499 $showCreditsIfMax = $config->get(
'ShowCreditsIfMax' );
2500 $useCredits = $titleExists
2501 && $out->isArticle()
2502 && $out->isRevisionCurrent()
2503 && $maxCredits !== 0;
2506 if ( $titleExists ) {
2507 $article = Article::newFromWikiPage( $this->getWikiPage(), $this );
2508 $action = Action::factory(
'credits', $article, $this );
2511 '@phan-var CreditsAction $action';
2514 'lastmod' => !$useCredits ? $this->lastModified() : null,
2515 'numberofwatchingusers' => null,
2516 'credits' => $useCredits ?
2517 $action->getCredits( $maxCredits, $showCreditsIfMax ) : null,
2518 'copyright' => $titleExists &&
2519 $out->showsCopyright() ? $this->getCopyright() : null,
2521 'places' => $this->getSiteFooterLinks(),
2523 foreach ( $data as $key => $existingItems ) {
2525 $this->getHookRunner()->onSkinAddFooterLinks( $this, $key, $newItems );
2526 $data[$key] = $existingItems + $newItems;
$wgFallbackSkin
Fallback skin used when the skin defined by $wgDefaultSkin can't be found.
$wgSkipSkins
Specify the names of skins that should not be presented in the list of available skins in user prefer...
$wgDefaultSkin
Default skin, for new users and anonymous visitors.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfExpandIRI( $url)
Take a URL, make sure it's expanded to fully qualified, and replace any encoded non-ASCII Unicode cha...
wfUrlProtocols( $includeProtocolRelative=true)
Returns a regular expression of url protocols.
wfMatchesDomainList( $url, $domains)
Check whether a given URL has a domain that occurs in a given set of domains.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that $function is deprecated.
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Marks HTML that shouldn't be escaped.
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Class representing a list of titles The execute() method checks them all for existence and adds them ...
static titleAttrib( $name, $options=null, array $msgParams=[])
Given the id of an interface element, constructs the appropriate title attribute from the system mess...
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
This is one of the Core classes and should be read at least once by any new developers.
static getAvailableLogos( $conf)
Return an array of all available logos that a skin may use.
static makeInlineScript( $script, $nonce=null)
Make an HTML script that runs given JS code after startup and base modules.
static makeConfigSetScript(array $configuration)
Return JS code which will set the MediaWiki configuration array to the given value.
The main skin class which provides methods and properties for all other skins.
aboutLink()
Gets the link to the wiki's about page.
isRevisionCurrent()
Whether the revision displayed is the latest revision of the page.
getFooterLinks()
Get template representation of the footer containing site footer links as well as standard footer lin...
static makeInternalOrExternalUrl( $name)
If url string starts with http, consider as external URL, else internal.
afterContentHook()
This runs a hook to allow extensions placing their stuff after content and article metadata (e....
buildFeedUrls()
Build data structure representing syndication links.
string $stylename
Stylesheets set to use.
getNewtalks()
Gets new talk page messages for the current user and returns an appropriate alert message (or an empt...
mainPageLink()
Gets the link to the wiki's main page.
static getAllowedSkins()
Fetch the list of user-selectable skins in regards to $wgSkipSkins.
doEditSectionLink(Title $nt, $section, $tooltip, Language $lang)
Create a section edit link.
getSkinStylePath( $name)
Return a fully resolved style path URL to images or styles stored in the current skin's folder.
getCachedNotice( $name)
Get a cached notice.
makeLink( $key, $item, $options=[])
Makes a link, usually used by makeListItem to generate a link for an item in a list used in navigatio...
static makeMainPageUrl( $urlaction='')
static makeKnownUrlDetails( $name, $urlaction='')
Make URL details where the article exists (or at least it's convenient to think so)
generateDebugHTML()
Generate debug data HTML for displaying at the bottom of the main content area.
privacyLink()
Gets the link to the wiki's privacy policy page.
footerLinkTitle( $desc, $page)
getSiteNotice()
Get the site notice.
getHtmlElementAttributes()
Return values for <html> element.
static getSkinNames()
Fetch the set of available skins.
static normalizeKey( $key)
Normalize a skin preference value to a form that can be loaded.
getSiteFooterLinks()
Gets the link to the wiki's privacy policy, about page, and disclaimer page.
getPoweredBy()
Gets the powered by MediaWiki icon.
outputPage()
Outputs the HTML generated by other functions.
mapInterwikiToLanguage( $code)
Allows correcting the language of interlanguage links which, mostly due to legacy reasons,...
static makeUrlDetails( $name, $urlaction='')
these return an array with the 'href' and boolean 'exists'
getLogo()
URL to the default square logo (1x key) Please use ResourceLoaderSkinModule::getAvailableLogos.
addToSidebar(&$bar, $message)
Add content from a sidebar system message Currently only used for MediaWiki:Sidebar (but may be used ...
static makeSpecialUrlSubpage( $name, $subpage, $urlaction='')
array $options
Skin options passed into constructor.
__construct( $options=null)
getRelevantUser()
Return the "relevant" user.
getIndicatorsData( $indicators)
Return an array of indicator data.
setRelevantTitle( $t)
Set the "relevant" title.
drawCategoryBrowser( $tree)
Render the array as a series of links.
getIndicatorsHTML( $indicators)
Get the suggested HTML for page status indicators: icons (or short text snippets) usually displayed i...
static checkTitle(&$title, $name)
make sure we have some title to operate on
static makeUrl( $name, $urlaction='')
getPageClasses( $title)
TODO: document.
editUrlOptions()
Return URL options for the 'edit page' link.
buildNavUrls()
Build array of common navigation links.
static makeNSUrl( $name, $urlaction='', $namespace=NS_MAIN)
this can be passed the NS number as defined in Language.php
buildSidebar()
Build an array that represents the sidebar(s), the navigation bar among them.
getCopyright( $type='detect')
printSource()
Text with the permalink to the source page, usually shown on the footer of a printed page.
getLanguages()
Generates array of language links for the current page.
setRelevantUser( $u)
Set the "relevant" user.
makeSearchInput( $attrs=[])
setupSkinUserCss(OutputPage $out)
Hook point for adding style modules to OutputPage.
makeSearchButton( $mode, $attrs=[])
makeFooterIcon( $icon, $withImage='withImage')
Renders a $wgFooterIcons icon according to the method's arguments.
getRevisionId()
Get the current revision ID.
getAfterPortlet(string $name)
Allows extensions to hook into known portlets and add stuff to them.
preloadExistence()
Preload the existence of three commonly-requested pages in a single query.
bottomScripts()
This gets called shortly before the "</body>" tag.
disclaimerLink()
Gets the link to the wiki's general disclaimers page.
getDefaultModules()
Defines the ResourceLoader modules that should be added to the skin It is recommended that skins wish...
static makeSpecialUrl( $name, $urlaction='', $proto=null)
Make a URL for a Special Page using the given query and protocol.
lastModified()
Get the timestamp of the latest revision, formatted in user language.
static makeVariablesScript( $data, $nonce=null)
initPage(OutputPage $out)
Stable to override.
makeListItem( $key, $item, $options=[])
Generates a list item for a navigation, portlet, portal, sidebar... list.
static getDynamicStylesheetQuery()
Get the query to generate a dynamic stylesheet.
subPageSubtitle( $out=null)
addToSidebarPlain(&$bar, $text)
Add content from plain text.
footerLink( $desc, $page)
Returns an HTML link for use in the footer.
static makeI18nUrl( $name, $urlaction='')
getPersonalToolsForMakeListItem( $urls)
Create an array of personal tools items from the data in the quicktemplate stored by SkinTemplate.
getRelevantTitle()
Return the "relevant" title.
makeToolbox( $navUrls, $feedUrls)
Create an array of common toolbox items from the data in the quicktemplate stored by SkinTemplate.
static validateTarget( $target, User $sender)
Validate target User.
setContext( $context)
Sets the context this SpecialPage is executed in.
static getSafeTitleFor( $name, $subpage=false)
Get a localised Title object for a page name with a possibly unvalidated subpage.
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,...
Represents a title within MediaWiki.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
static newFromId( $id)
Static factory method for creation from a given user ID.
static isIP( $name)
Does the string match an anonymous IP address?
Special page to allow managing user group membership.
if(!isset( $args[0])) $lang
if(!file_exists( $CREDITS)) $lines