69 return new $classname( $this->
getConfig() );
86 foreach ( $this->
getOutput()->getLanguageLinks() as $languageLinkText ) {
87 $class =
'interlanguage-link interwiki-' . explode(
':', $languageLinkText, 2 )[0];
89 $languageLinkTitle = Title::newFromText( $languageLinkText );
90 if ( $languageLinkTitle ) {
91 $ilInterwikiCode = $languageLinkTitle->getInterwiki();
92 $ilLangName = Language::fetchLanguageName( $ilInterwikiCode );
94 if ( strval( $ilLangName ) ===
'' ) {
95 $ilDisplayTextMsg =
wfMessage(
"interlanguage-link-$ilInterwikiCode" );
96 if ( !$ilDisplayTextMsg->isDisabled() ) {
98 $ilLangName = $ilDisplayTextMsg->text();
101 $ilLangName = $languageLinkText;
110 $ilLangLocalName = Language::fetchLanguageName(
115 $languageLinkTitleText = $languageLinkTitle->getText();
116 if ( $ilLangLocalName ===
'' ) {
117 $ilFriendlySiteName =
wfMessage(
"interlanguage-link-sitename-$ilInterwikiCode" );
118 if ( !$ilFriendlySiteName->isDisabled() ) {
119 if ( $languageLinkTitleText ===
'' ) {
121 'interlanguage-link-title-nonlangonly',
122 $ilFriendlySiteName->text()
126 'interlanguage-link-title-nonlang',
127 $languageLinkTitleText,
128 $ilFriendlySiteName->text()
135 $ilTitle = $languageLinkTitle->getInterwiki() .
136 ":$languageLinkTitleText";
138 } elseif ( $languageLinkTitleText ===
'' ) {
140 'interlanguage-link-title-langonly',
145 'interlanguage-link-title',
146 $languageLinkTitleText,
151 $ilInterwikiCodeBCP47 = LanguageCode::bcp47( $ilInterwikiCode );
153 'href' => $languageLinkTitle->getFullURL(),
154 'text' => $ilLangName,
157 'link-class' =>
'interlanguage-link-target',
158 'lang' => $ilInterwikiCodeBCP47,
159 'hreflang' => $ilInterwikiCodeBCP47,
162 'SkinTemplateGetLanguageLink',
165 $languageLinks[] = $languageLink;
169 return $languageLinks;
182 $this->thispage =
$title->getPrefixedDBkey();
183 $this->titletxt =
$title->getPrefixedText();
184 $this->userpage = $user->getUserPage()->getPrefixedText();
186 if ( !$request->wasPosted() ) {
187 $query = $request->getValues();
188 unset( $query[
'title'] );
189 unset( $query[
'returnto'] );
190 unset( $query[
'returntoquery'] );
193 $this->loggedin = $user->isLoggedIn();
194 $this->username = $user->getName();
196 if ( $this->loggedin ) {
199 # This won't be used in the standard skins, but we define it to preserve the interface
200 # To save time, we check for existence
211 Profiler::instance()->setAllowOutput();
217 $res = $tpl->execute();
231 # An ID that includes the actual body text; without categories, contentSub, ...
232 $realBodyAttribs = [
'id' =>
'mw-content-text' ];
234 # Add a mw-content-ltr/rtl class to be able to style based on text
235 # direction when the content is different from the UI language (only
237 # Most information on special pages and file pages is in user language,
238 # rather than content language, so those will not get this
239 if ( Action::getActionName( $this ) ===
'view' &&
241 $pageLang =
$title->getPageViewLanguage();
242 $realBodyAttribs[
'lang'] = $pageLang->getHtmlCode();
243 $realBodyAttribs[
'dir'] = $pageLang->getDir();
244 $realBodyAttribs[
'class'] =
'mw-content-' . $pageLang->getDir();
247 return Html::rawElement(
'div', $realBodyAttribs, $html );
267 $tpl->set(
'title', $out->getPageTitle() );
268 $tpl->set(
'pagetitle', $out->getHTMLTitle() );
269 $tpl->set(
'displaytitle', $out->mPageLinkTitle );
271 $tpl->set(
'thispage', $this->thispage );
272 $tpl->set(
'titleprefixeddbkey', $this->thispage );
273 $tpl->set(
'titletext',
$title->getText() );
274 $tpl->set(
'articleid',
$title->getArticleID() );
276 $tpl->set(
'isarticle', $out->isArticle() );
279 if ( $subpagestr !==
'' ) {
280 $subpagestr =
'<span class="subpages">' . $subpagestr .
'</span>';
282 $tpl->set(
'subtitle', $subpagestr . $out->getSubtitle() );
285 if ( $undelete ===
'' ) {
286 $tpl->set(
'undelete',
'' );
288 $tpl->set(
'undelete',
'<span class="subpages">' . $undelete .
'</span>' );
292 if ( $out->isSyndicated() ) {
294 foreach ( $out->getSyndicationLinks() as $format => $link ) {
297 'text' => $this->
msg(
"feed-$format" )->text(),
301 $tpl->set(
'feeds', $feeds );
303 $tpl->set(
'feeds',
false );
307 $tpl->set(
'charset',
'UTF-8' );
309 $tpl->set(
'skinname', $this->skinname );
310 $tpl->set(
'skinclass', static::class );
311 $tpl->set(
'skin', $this );
312 $tpl->set(
'stylename', $this->stylename );
313 $tpl->set(
'printable', $out->isPrintable() );
314 $tpl->set(
'handheld', $request->getBool(
'handheld' ) );
315 $tpl->set(
'loggedin', $this->loggedin );
316 $tpl->set(
'notspecialpage', !
$title->isSpecialPage() );
318 $tpl->set(
'searchtitle', SpecialPage::getTitleFor(
'Search' )->getPrefixedDBkey() );
319 $tpl->set(
'search', trim( $request->getVal(
'search' ) ) );
324 $tpl->set(
'logopath',
$wgLogo );
328 $userLangCode = $userLang->getHtmlCode();
329 $userLangDir = $userLang->getDir();
331 $tpl->set(
'lang', $userLangCode );
332 $tpl->set(
'dir', $userLangDir );
333 $tpl->set(
'rtl', $userLang->isRTL() );
335 $tpl->set(
'capitalizeallnouns', $userLang->capitalizeAllNouns() ?
' capitalize-all-nouns' :
'' );
336 $tpl->set(
'showjumplinks',
true );
337 $tpl->set(
'username', $this->loggedin ? $this->username : null );
338 $tpl->set(
'userpage', $this->userpage );
339 $tpl->set(
'userpageurl', $this->userpageUrlDetails[
'href'] );
340 $tpl->set(
'userlang', $userLangCode );
345 $tpl->set(
'userlangattributes',
'' );
346 $tpl->set(
'specialpageattributes',
'' ); # obsolete
349 $tpl->set(
'prebodyhtml',
'' );
351 $contLang = MediaWikiServices::getInstance()->getContentLanguage();
353 $userLangCode !== $contLang->getHtmlCode() ||
354 $userLangDir !== $contLang->getDir()
356 $escUserlang = htmlspecialchars( $userLangCode );
357 $escUserdir = htmlspecialchars( $userLangDir );
360 $attrs =
" lang=\"$escUserlang\" dir=\"$escUserdir\"";
361 $tpl->set(
'userlangattributes', $attrs );
365 $tpl->set(
'logo', $this->
logoText() );
367 $tpl->set(
'copyright',
false );
369 $tpl->set(
'viewcount',
false );
370 $tpl->set(
'lastmod',
false );
371 $tpl->set(
'credits',
false );
372 $tpl->set(
'numberofwatchingusers',
false );
374 if ( $out->isArticle() && $out->isRevisionCurrent() ) {
377 $action = Action::factory(
379 '@phan-var CreditsAction $action';
380 $tpl->set(
'credits',
386 if ( $out->showsCopyright() ) {
395 $tpl->set(
'about', $this->
aboutLink() );
397 $tpl->set(
'footerlinks', [
400 'numberofwatchingusers',
413 foreach ( $tpl->data[
'footericons'] as $footerIconsKey => &$footerIconsBlock ) {
414 if ( count( $footerIconsBlock ) > 0 ) {
415 foreach ( $footerIconsBlock as &$footerIcon ) {
416 if ( isset( $footerIcon[
'src'] ) ) {
417 if ( !isset( $footerIcon[
'width'] ) ) {
418 $footerIcon[
'width'] = 88;
420 if ( !isset( $footerIcon[
'height'] ) ) {
421 $footerIcon[
'height'] = 31;
426 unset( $tpl->data[
'footericons'][$footerIconsKey] );
430 $tpl->set(
'indicators', $out->getIndicators() );
436 $tpl->set(
'bodytext', $out->mBodytext );
439 if ( count( $language_urls ) ) {
440 $tpl->set(
'language_urls', $language_urls );
442 $tpl->set(
'language_urls',
false );
449 $tpl->set(
'content_navigation', $content_navigation );
450 $tpl->set(
'content_actions', $content_actions );
459 $tpl->set(
'headelement', $out->headElement( $this ) );
461 $tpl->set(
'debug',
'' );
463 $tpl->set(
'reporttime',
wfReportTime( $out->getCSPNonce() ) );
466 $skinTemplate = $this;
468 if ( !Hooks::run(
'SkinTemplateOutputPageBeforeExec', [ &$skinTemplate, &$tpl ] ) ) {
469 wfDebug( __METHOD__ .
": Hook SkinTemplateOutputPageBeforeExec broke outputPage execution!\n" );
474 $tpl->set(
'bodycontent', $tpl->data[
'bodytext'] );
479 $tpl->data[
'bodytext'] .= Html::rawElement(
481 [
'class' =>
'printfooter' ],
482 "\n{$tpl->data['printfooter']}"
484 $tpl->data[
'bodytext'] .= $tpl->data[
'debughtml'];
515 if ( $personalTools ===
null ) {
517 ? $tpl->getPersonalTools()
521 foreach ( $personalTools as $key => $item ) {
522 $html .= $tpl->makeListItem( $key, $item, $options );
539 return ( $tpl instanceof
BaseTemplate ) ? $tpl->getPersonalTools() : [];
587 $pageurl =
$title->getLocalURL();
588 $authManager = AuthManager::singleton();
589 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
594 # Due to T34276, if a user does not have read permissions,
595 # $this->getTitle() will just give Special:Badtitle, which is
596 # not especially useful as a returnto parameter. Use the title
597 # from the request instead, if there was one.
598 if ( $permissionManager->userHasRight( $this->getUser(),
'read' ) ) {
601 $page = Title::newFromText( $request->getVal(
'title',
'' ) );
603 $page = $request->getVal(
'returnto', $page );
605 if ( strval( $page ) !==
'' ) {
606 $returnto[
'returnto'] = $page;
607 $query = $request->getVal(
'returntoquery', $this->thisquery );
610 if ( $query !=
'' ) {
611 $returnto[
'returntoquery'] = $query;
615 if ( $this->loggedin ) {
616 $personal_urls[
'userpage'] = [
618 'href' => &$this->userpageUrlDetails[
'href'],
619 'class' => $this->userpageUrlDetails[
'exists'] ? false :
'new',
620 'exists' => $this->userpageUrlDetails[
'exists'],
621 'active' => ( $this->userpageUrlDetails[
'href'] == $pageurl ),
625 $personal_urls[
'mytalk'] = [
626 'text' => $this->
msg(
'mytalk' )->text(),
627 'href' => &$usertalkUrlDetails[
'href'],
628 'class' => $usertalkUrlDetails[
'exists'] ? false :
'new',
629 'exists' => $usertalkUrlDetails[
'exists'],
630 'active' => ( $usertalkUrlDetails[
'href'] == $pageurl )
633 $personal_urls[
'preferences'] = [
634 'text' => $this->
msg(
'mypreferences' )->text(),
636 'active' => ( $href == $pageurl )
639 if ( $permissionManager->userHasRight( $this->getUser(),
'viewmywatchlist' ) ) {
641 $personal_urls[
'watchlist'] = [
642 'text' => $this->
msg(
'mywatchlist' )->text(),
644 'active' => ( $href == $pageurl )
648 # We need to do an explicit check for Special:Contributions, as we
649 # have to match both the title, and the target, which could come
650 # from request values (Special:Contributions?target=Jimbo_Wales)
651 # or be specified in "sub page" form
652 # (Special:Contributions/Jimbo_Wales). The plot
653 # thickens, because the Title object is altered for special pages,
654 # so it doesn't contain the original alias-with-subpage.
655 $origTitle = Title::newFromText( $request->getText(
'title' ) );
657 list( $spName, $spPar ) =
658 MediaWikiServices::getInstance()->getSpecialPageFactory()->
659 resolveAlias( $origTitle->getText() );
660 $active = $spName ==
'Contributions'
668 $personal_urls[
'mycontris'] = [
669 'text' => $this->
msg(
'mycontris' )->text(),
675 if ( $request->getSession()->canSetUser() ) {
676 $personal_urls[
'logout'] = [
677 'text' => $this->
msg(
'pt-userlogout' )->text(),
678 'data-mw' =>
'interface',
682 (
$title->isSpecial(
'Preferences' ) ? [] : $returnto ) ),
688 if ( !$authManager->canCreateAccounts() || !$authManager->canAuthenticateNow() ) {
690 $useCombinedLoginLink =
false;
693 $loginlink = $permissionManager->userHasRight( $this->
getUser(),
'createaccount' )
694 && $useCombinedLoginLink ?
'nav-login-createaccount' :
'pt-login';
697 'text' => $this->
msg( $loginlink )->text(),
699 'active' =>
$title->isSpecial(
'Userlogin' )
700 ||
$title->isSpecial(
'CreateAccount' ) && $useCombinedLoginLink,
702 $createaccount_url = [
703 'text' => $this->
msg(
'pt-createaccount' )->text(),
705 'active' =>
$title->isSpecial(
'CreateAccount' ),
709 if ( $permissionManager->groupHasPermission(
'*',
'edit' ) ) {
716 $personal_urls[
'anontalk'] = [
717 'text' => $this->
msg(
'anontalk' )->text(),
721 $personal_urls[
'anoncontribs'] = [
722 'text' => $this->
msg(
'anoncontribs' )->text(),
729 $authManager->canCreateAccounts()
730 && $permissionManager->userHasRight( $this->getUser(),
'createaccount' )
731 && !$useCombinedLoginLink
733 $personal_urls[
'createaccount'] = $createaccount_url;
736 if ( $authManager->canAuthenticateNow() ) {
737 $key = $permissionManager->groupHasPermission(
'*',
'read' )
740 $personal_urls[$key] = $login_url;
744 Hooks::runWithoutAbort(
'PersonalUrls', [ &$personal_urls, &
$title, $this ] );
745 return $personal_urls;
762 $classes[] =
'selected';
765 if ( $checkEdit && !
$title->isKnown() ) {
768 if ( $query !==
'' ) {
769 $query =
'action=edit&redlink=1&' . $query;
771 $query =
'action=edit&redlink=1';
775 $services = MediaWikiServices::getInstance();
776 $linkClass = $services->getLinkRenderer()->getLinkClasses(
$title );
781 if ( is_array( $message ) ) {
783 $message = end( $message );
785 if ( $msg->exists() ) {
786 $text = $msg->text();
788 $text = $services->getContentLanguage()->getConverter()->
789 convertNamespace( $services->getNamespaceInfo()->
790 getSubject(
$title->getNamespace() ) );
794 $skinTemplate = $this;
796 if ( !Hooks::run(
'SkinTemplateTabAction', [ &$skinTemplate,
797 $title, $message, $selected, $checkEdit,
798 &$classes, &$query, &$text, &$result ] ) ) {
803 'class' => implode(
' ', $classes ),
805 'href' =>
$title->getLocalURL( $query ),
808 if ( $linkClass !==
'' ) {
809 $result[
'link-class'] = $linkClass;
816 $title = Title::newFromText( $name );
817 if ( !is_object(
$title ) ) {
818 throw new MWException( __METHOD__ .
" given invalid pagename $name" );
823 'href' =>
$title->getLocalURL( $urlaction ),
824 'exists' =>
$title->isKnown(),
835 $title = Title::newFromText( $name );
839 'href' =>
$title->getLocalURL( $urlaction ),
840 'exists' =>
$title->exists(),
888 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
890 $content_navigation = [
898 $action = $request->getVal(
'action',
'view' );
900 $userCanRead = $permissionManager->quickUserCan(
'read', $user,
$title );
903 $skinTemplate = $this;
904 $preventActiveTabs =
false;
905 Hooks::run(
'SkinTemplatePreventOtherActiveTabs', [ &$skinTemplate, &$preventActiveTabs ] );
908 if (
$title->canExist() ) {
910 $subjectPage =
$title->getSubjectPage();
911 $talkPage =
$title->getTalkPage();
914 $isTalk =
$title->isTalkPage();
917 $subjectId =
$title->getNamespaceKey(
'' );
919 if ( $subjectId ==
'main' ) {
922 $talkId =
"{$subjectId}_talk";
928 $subjectMsg = [
"nstab-$subjectId" ];
929 if ( $subjectPage->isMainPage() ) {
930 array_unshift( $subjectMsg,
'mainpage-nstab' );
932 $content_navigation[
'namespaces'][$subjectId] = $this->
tabAction(
933 $subjectPage, $subjectMsg, !$isTalk && !$preventActiveTabs,
'', $userCanRead
935 $content_navigation[
'namespaces'][$subjectId][
'context'] =
'subject';
936 $content_navigation[
'namespaces'][$talkId] = $this->
tabAction(
937 $talkPage, [
"nstab-$talkId",
'talk' ], $isTalk && !$preventActiveTabs,
'', $userCanRead
939 $content_navigation[
'namespaces'][$talkId][
'context'] =
'talk';
941 if ( $userCanRead ) {
943 if (
$title->isKnown() ) {
944 $content_navigation[
'views'][
'view'] = $this->
tabAction(
945 $isTalk ? $talkPage : $subjectPage,
946 [
"$skname-view-view",
'view' ],
947 ( $onPage && ( $action ==
'view' || $action ==
'purge' ) ),
'',
true
950 $content_navigation[
'views'][
'view'][
'redundant'] =
true;
954 $isRemoteContent = $page && !$page->isLocal();
958 if ( $isRemoteContent ) {
959 $content_navigation[
'views'][
'view-foreign'] = [
963 params( $page->getWikiDisplayName() )->text(),
964 'href' => $page->getSourceURL(),
970 if ( $permissionManager->quickUserCan(
'edit', $user,
$title ) &&
972 $permissionManager->quickUserCan(
'create', $user,
$title ) )
975 $isTalkClass = $isTalk ?
' istalk' :
'';
977 $isEditing = $onPage && ( $action ==
'edit' || $action ==
'submit' );
980 $showNewSection = !$out->forceHideNewSectionLink()
981 && ( ( $isTalk && $out->isRevisionCurrent() ) || $out->showNewSectionLink() );
982 $section = $request->getVal(
'section' );
986 &&
$title->getDefaultMessageText() !== false
989 $msgKey = $isRemoteContent ?
'edit-local' :
'edit';
991 $msgKey = $isRemoteContent ?
'create-local' :
'create';
993 $content_navigation[
'views'][
'edit'] = [
994 'class' => ( $isEditing && ( $section !==
'new' || !$showNewSection )
1001 'primary' => !$isRemoteContent,
1005 if ( $showNewSection ) {
1008 $content_navigation[
'views'][
'addsection'] = [
1009 'class' => ( $isEditing && $section ==
'new' ) ?
'selected' :
false,
1012 'href' =>
$title->getLocalURL(
'action=edit§ion=new' )
1016 } elseif (
$title->hasSourceText() ) {
1018 $content_navigation[
'views'][
'viewsource'] = [
1019 'class' => ( $onPage && $action ==
'edit' ) ?
'selected' :
false,
1028 if (
$title->exists() ) {
1030 $content_navigation[
'views'][
'history'] = [
1031 'class' => ( $onPage && $action ==
'history' ) ?
'selected' :
false,
1034 'href' =>
$title->getLocalURL(
'action=history' ),
1037 if ( $permissionManager->quickUserCan(
'delete', $user,
$title ) ) {
1038 $content_navigation[
'actions'][
'delete'] = [
1039 'class' => ( $onPage && $action ==
'delete' ) ?
'selected' :
false,
1042 'href' =>
$title->getLocalURL(
'action=delete' )
1046 if ( $permissionManager->quickUserCan(
'move', $user,
$title ) ) {
1047 $moveTitle = SpecialPage::getTitleFor(
'Movepage',
$title->getPrefixedDBkey() );
1048 $content_navigation[
'actions'][
'move'] = [
1049 'class' => $this->
getTitle()->isSpecial(
'Movepage' ) ?
'selected' :
false,
1052 'href' => $moveTitle->getLocalURL()
1057 if ( $permissionManager->quickUserCan(
'deletedhistory', $user,
$title ) ) {
1058 $n =
$title->isDeleted();
1060 $undelTitle = SpecialPage::getTitleFor(
'Undelete',
$title->getPrefixedDBkey() );
1063 $msgKey = $permissionManager->quickUserCan(
'undelete',
1064 $user,
$title ) ?
'undelete' :
'viewdeleted';
1065 $content_navigation[
'actions'][
'undelete'] = [
1066 'class' => $this->
getTitle()->isSpecial(
'Undelete' ) ?
'selected' :
false,
1068 ->setContext( $this->
getContext() )->numParams( $n )->text(),
1069 'href' => $undelTitle->getLocalURL()
1075 if ( $permissionManager->quickUserCan(
'protect', $user,
$title ) &&
1076 $title->getRestrictionTypes() &&
1077 $permissionManager->getNamespaceRestrictionLevels(
$title->getNamespace(), $user ) !== [
'' ]
1079 $mode =
$title->isProtected() ?
'unprotect' :
'protect';
1080 $content_navigation[
'actions'][$mode] = [
1081 'class' => ( $onPage && $action == $mode ) ?
'selected' :
false,
1084 'href' =>
$title->getLocalURL(
"action=$mode" )
1089 if ( $this->loggedin && $permissionManager->userHasAllRights( $user,
1090 'viewmywatchlist',
'editmywatchlist' )
1101 $mode = $user->isWatched(
$title ) ?
'unwatch' :
'watch';
1102 $content_navigation[
'actions'][$mode] = [
1103 'class' =>
'mw-watchlink ' . (
1104 $onPage && ( $action ==
'watch' || $action ==
'unwatch' ) ?
'selected' :
''
1107 'text' => $this->
msg( $mode )->text(),
1108 'href' =>
$title->getLocalURL( [
'action' => $mode ] ),
1112 'mw' =>
'interface',
1119 $skinTemplate = $this;
1120 Hooks::runWithoutAbort(
1121 'SkinTemplateNavigation',
1122 [ &$skinTemplate, &$content_navigation ]
1126 $pageLang =
$title->getPageLanguage();
1129 if ( $pageLang->hasVariants() ) {
1131 $variants = $pageLang->getVariants();
1134 $preferred = $pageLang->getPreferredVariant();
1135 if ( Action::getActionName( $this ) ===
'view' ) {
1136 $params = $request->getQueryValues();
1137 unset( $params[
'title'] );
1142 foreach ( $variants as $code ) {
1144 $varname = $pageLang->getVariantname( $code );
1146 $content_navigation[
'variants'][] = [
1147 'class' => ( $code == $preferred ) ?
'selected' :
false,
1149 'href' =>
$title->getLocalURL( [
'variant' => $code ] + $params ),
1150 'lang' => LanguageCode::bcp47( $code ),
1151 'hreflang' => LanguageCode::bcp47( $code ),
1158 $content_navigation[
'namespaces'][
'special'] = [
1159 'class' =>
'selected',
1160 'text' => $this->
msg(
'nstab-special' )->text(),
1161 'href' => $request->getRequestURL(),
1162 'context' =>
'subject'
1166 $skinTemplate = $this;
1167 Hooks::runWithoutAbort(
'SkinTemplateNavigation::SpecialPage',
1168 [ &$skinTemplate, &$content_navigation ] );
1172 $skinTemplate = $this;
1174 Hooks::runWithoutAbort(
'SkinTemplateNavigation::Universal',
1175 [ &$skinTemplate, &$content_navigation ] );
1178 foreach ( $content_navigation as $section => &$links ) {
1179 foreach ( $links as $key => &$link ) {
1181 if ( isset( $link[
'context'] ) && $link[
'context'] ==
'subject' ) {
1182 $xmlID =
'ca-nstab-' . $xmlID;
1183 } elseif ( isset( $link[
'context'] ) && $link[
'context'] ==
'talk' ) {
1185 $link[
'rel'] =
'discussion';
1186 } elseif ( $section ==
'variants' ) {
1187 $xmlID =
'ca-varlang-' . $xmlID;
1189 $xmlID =
'ca-' . $xmlID;
1191 $link[
'id'] = $xmlID;
1195 # We don't want to give the watch tab an accesskey if the
1196 # page is being edited, because that conflicts with the
1197 # accesskey on the watch checkbox. We also don't want to
1198 # give the edit tab an accesskey, because that's fairly
1199 # superfluous and conflicts with an accesskey (Ctrl-E) often
1200 # used for editing in Safari.
1201 if ( in_array( $action, [
'edit',
'submit' ] ) ) {
1202 if ( isset( $content_navigation[
'views'][
'edit'] ) ) {
1203 $content_navigation[
'views'][
'edit'][
'tooltiponly'] =
true;
1205 if ( isset( $content_navigation[
'actions'][
'watch'] ) ) {
1206 $content_navigation[
'actions'][
'watch'][
'tooltiponly'] =
true;
1208 if ( isset( $content_navigation[
'actions'][
'unwatch'] ) ) {
1209 $content_navigation[
'actions'][
'unwatch'][
'tooltiponly'] =
true;
1213 return $content_navigation;
1226 $content_actions = [];
1228 foreach ( $content_navigation as $links ) {
1229 foreach ( $links as $key => $value ) {
1230 if ( isset( $value[
'redundant'] ) && $value[
'redundant'] ) {
1239 if ( isset( $value[
'id'] ) && substr( $value[
'id'], 0, 3 ) ==
'ca-' ) {
1240 $key = substr( $value[
'id'], 3 );
1243 if ( isset( $content_actions[$key] ) ) {
1244 wfDebug( __METHOD__ .
": Found a duplicate key for $key while flattening " .
1245 "content_navigation into content_actions.\n" );
1249 $content_actions[$key] = $value;
1253 return $content_actions;
1273 $nav_urls[
'upload'] =
false;
1277 $nav_urls[
'print'] =
false;
1278 $nav_urls[
'permalink'] =
false;
1279 $nav_urls[
'info'] =
false;
1280 $nav_urls[
'whatlinkshere'] =
false;
1281 $nav_urls[
'recentchangeslinked'] =
false;
1282 $nav_urls[
'contributions'] =
false;
1283 $nav_urls[
'log'] =
false;
1284 $nav_urls[
'blockip'] =
false;
1285 $nav_urls[
'mute'] =
false;
1286 $nav_urls[
'emailuser'] =
false;
1287 $nav_urls[
'userrights'] =
false;
1291 if ( !$out->isPrintable() && ( $out->isArticle() || $this->getTitle()->isSpecialPage() ) ) {
1292 $nav_urls[
'print'] = [
1293 'text' => $this->
msg(
'printableversion' )->text(),
1294 'href' => $this->
getTitle()->getLocalURL(
1295 $request->appendQueryValue(
'printable',
'yes' ) )
1299 if ( $out->isArticle() ) {
1301 $revid = $this->
getOutput()->getRevisionId();
1303 $nav_urls[
'permalink'] = [
1304 'text' => $this->
msg(
'permalink' )->text(),
1305 'href' => $this->
getTitle()->getLocalURL(
"oldid=$revid" )
1310 $skinTemplate = $this;
1312 Hooks::run(
'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink',
1313 [ &$skinTemplate, &$nav_urls, &$revid, &$revid ] );
1316 if ( $out->isArticleRelated() ) {
1317 $nav_urls[
'whatlinkshere'] = [
1318 'href' => SpecialPage::getTitleFor(
'Whatlinkshere', $this->thispage )->getLocalURL()
1321 $nav_urls[
'info'] = [
1322 'text' => $this->
msg(
'pageinfo-toolboxlink' )->text(),
1323 'href' => $this->
getTitle()->getLocalURL(
"action=info" )
1327 $nav_urls[
'recentchangeslinked'] = [
1328 'href' => SpecialPage::getTitleFor(
'Recentchangeslinked', $this->thispage )->getLocalURL()
1335 $rootUser = $user->getName();
1337 $nav_urls[
'contributions'] = [
1338 'text' => $this->
msg(
'contributions', $rootUser )->text(),
1340 'tooltip-params' => [ $rootUser ],
1343 $nav_urls[
'log'] = [
1347 if ( MediawikiServices::getInstance()
1349 ->userHasRight( $this->
getUser(),
'block' )
1351 $nav_urls[
'blockip'] = [
1352 'text' => $this->
msg(
'blockip', $rootUser )->text(),
1358 $nav_urls[
'emailuser'] = [
1359 'text' => $this->
msg(
'tool-link-emailuser', $rootUser )->text(),
1361 'tooltip-params' => [ $rootUser ],
1365 if ( !$user->isAnon() ) {
1366 if ( $this->
getUser()->isRegistered() && $this->
getConfig()->
get(
'EnableSpecialMute' ) ) {
1367 $nav_urls[
'mute'] = [
1368 'text' => $this->
msg(
'mute-preferences' )->text(),
1375 $canChange = $sur->userCanChangeRights( $user );
1376 $nav_urls[
'userrights'] = [
1377 'text' => $this->
msg(
1378 $canChange ?
'tool-link-userrights' :
'tool-link-userrights-readonly',
1394 return $this->
getTitle()->getNamespaceKey();
$wgScript
The URL path to index.php.
$wgMimeType
The default Content-Type header.
$wgDisableLangConversion
Whether to enable language variant conversion.
$wgSitename
Name of the site.
$wgUseCombinedLoginLink
Login / create account link behavior when it's possible for anonymous users to create an account.
$wgHideInterlanguageLinks
Hide interlanguage links from the sidebar.
$wgShowCreditsIfMax
If there are more than $wgMaxCredits authors, show $wgMaxCredits of them.
$wgFooterIcons
Abstract list of footer icons for skins in place of old copyrightico and poweredbyico code You can ad...
$wgUploadNavigationUrl
Point the upload navigation link to an external URL Useful if you want to use a shared repository by ...
$wgScriptPath
The path we should point to.
$wgStylePath
The URL path of the skins directory.
$wgServer
URL of the server.
$wgLogo
The URL path of the wiki logo.
$wgMaxCredits
Set this to the number of authors that you want to be credited below an article text.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfReportTime( $nonce=null)
Returns a script tag that stores the amount of time it took MediaWiki to handle the request in millis...
wfMessageFallback(... $keys)
This function accepts multiple message keys and returns a message instance for the first message whic...
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
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.
New base template for a skin's template extended from QuickTemplate this class features helper method...
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
canUseWikiPage()
Check whether a WikiPage object can be get with getWikiPage().
getWikiPage()
Get the WikiPage object.
getContext()
Get the base IContextSource object.
setContext(IContextSource $context)
Base class for template-based skins.
outputPage()
Initialize various variables and generate the template.
string $template
For QuickTemplate, the name of the subclass which will actually fill the template.
formatLanguageName( $name)
Format language name for use in sidebar interlanguage links list.
prepareQuickTemplate()
initialize various variables and generate the template
getPersonalToolsList()
Get the HTML for the p-personal list.
setupTemplate( $classname)
Create the template engine object; we feed it a bunch of data and eventually it spits out some HTML.
buildPersonalUrls()
build array of urls for personal toolbar
buildContentNavigationUrls()
a structured array of links usually used for the tabs in a skin
useCombinedLoginLink()
Output a boolean indicating if buildPersonalUrls should output separate login and create account link...
getStructuredPersonalTools()
Get personal tools for the user.
getLanguages()
Generates array of language links for the current page.
wrapHTML( $title, $html)
Wrap the body text with language information and identifiable element.
makeTalkUrlDetails( $name, $urlaction='')
makePersonalToolsList( $personalTools=null, $options=[])
Get the HTML for the personal tools list.
buildNavUrls()
build array of common navigation links
string $skinname
Name of our skin, it probably needs to be all lower case.
buildContentActionUrls( $content_navigation)
an array of edit links by default used for the tabs
makeArticleUrlDetails( $name, $urlaction='')
tabAction( $title, $message, $selected, $query='', $checkEdit=false)
Builds an array with tab definition.
getNameSpaceKey()
Generate strings used for xml 'id' names.
printOrError( $str)
Output the string, or print error message if it's an error object of the appropriate type.
The main skin class which provides methods and properties for all other skins.
aboutLink()
Gets the link to the wiki's about page.
afterContentHook()
This runs a hook to allow extensions placing their stuff after content and article metadata (e....
getNewtalks()
Gets new talk page messages for the current user and returns an appropriate alert message (or an empt...
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.
getSiteNotice()
Get the site notice.
getPoweredBy()
Gets the powered by MediaWiki icon.
static makeUrlDetails( $name, $urlaction='')
these return an array with the 'href' and boolean 'exists'
static makeSpecialUrlSubpage( $name, $subpage, $urlaction='')
getRelevantUser()
Return the "relevant" user.
static checkTitle(&$title, $name)
make sure we have some title to operate on
editUrlOptions()
Return URL options for the 'edit page' link.
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.
bottomScripts()
This gets called shortly before the "</body>" tag.
disclaimerLink()
Gets the link to the wiki's general disclaimers page.
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.
initPage(OutputPage $out)
subPageSubtitle( $out=null)
getRelevantTitle()
Return the "relevant" title.
setContext( $context)
Sets the context this SpecialPage is executed in.
Represents a title within MediaWiki.
isSpecialPage()
Returns true if this is a special page.
static isEnabled()
Returns true if uploads are enabled.
static isAllowed(UserIdentity $user)
Returns true if the user can use this upload module or else a string identifying the missing permissi...
Special page to allow managing user group membership.