MediaWiki REL1_34
Skin.php
Go to the documentation of this file.
1<?php
24use Wikimedia\WrappedString;
25use Wikimedia\WrappedStringList;
26
38abstract class Skin extends ContextSource {
42 protected $skinname = null;
43
44 protected $mRelevantTitle = null;
45 protected $mRelevantUser = null;
46
51 public $stylename = null;
52
57 static function getSkinNames() {
58 $skinFactory = MediaWikiServices::getInstance()->getSkinFactory();
59 return $skinFactory->getSkinNames();
60 }
61
67 static function getSkinNameMessages() {
68 wfDeprecated( __METHOD__, '1.34' );
69 $messages = [];
70 foreach ( self::getSkinNames() as $skinKey => $skinName ) {
71 $messages[] = "skinname-$skinKey";
72 }
73 return $messages;
74 }
75
83 public static function getAllowedSkins() {
84 global $wgSkipSkins;
85
86 $allowedSkins = self::getSkinNames();
87
88 foreach ( $wgSkipSkins as $skip ) {
89 unset( $allowedSkins[$skip] );
90 }
91
92 return $allowedSkins;
93 }
94
104 static function normalizeKey( $key ) {
106
107 $skinNames = self::getSkinNames();
108
109 // Make keys lowercase for case-insensitive matching.
110 $skinNames = array_change_key_case( $skinNames, CASE_LOWER );
111 $key = strtolower( $key );
112 $defaultSkin = strtolower( $wgDefaultSkin );
113 $fallbackSkin = strtolower( $wgFallbackSkin );
114
115 if ( $key == '' || $key == 'default' ) {
116 // Don't return the default immediately;
117 // in a misconfiguration we need to fall back.
118 $key = $defaultSkin;
119 }
120
121 if ( isset( $skinNames[$key] ) ) {
122 return $key;
123 }
124
125 // Older versions of the software used a numeric setting
126 // in the user preferences.
127 $fallback = [
128 0 => $defaultSkin,
129 2 => 'cologneblue'
130 ];
131
132 if ( isset( $fallback[$key] ) ) {
133 $key = $fallback[$key];
134 }
135
136 if ( isset( $skinNames[$key] ) ) {
137 return $key;
138 } elseif ( isset( $skinNames[$defaultSkin] ) ) {
139 return $defaultSkin;
140 } else {
141 return $fallbackSkin;
142 }
143 }
144
149 public function __construct( $skinname = null ) {
150 if ( is_string( $skinname ) ) {
151 $this->skinname = $skinname;
152 }
153 }
154
158 public function getSkinName() {
159 return $this->skinname;
160 }
161
165 public function initPage( OutputPage $out ) {
166 $this->preloadExistence();
167 }
168
179 public function getDefaultModules() {
180 $out = $this->getOutput();
181 $user = $this->getUser();
182
183 // Modules declared in the $modules literal are loaded
184 // for ALL users, on ALL pages, in ALL skins.
185 // Keep this list as small as possible!
186 $modules = [
187 'styles' => [
188 // The 'styles' key sets render-blocking style modules
189 // Unlike other keys in $modules, this is an associative array
190 // where each key is its own group pointing to a list of modules
191 'core' => [
192 'mediawiki.legacy.shared',
193 'mediawiki.legacy.commonPrint',
194 ],
195 'content' => [],
196 'syndicate' => [],
197 ],
198 'core' => [
199 'site',
200 'mediawiki.page.startup',
201 ],
202 // modules that enhance the content in some way
203 'content' => [
204 'mediawiki.page.ready',
205 ],
206 // modules relating to search functionality
207 'search' => [
208 'mediawiki.searchSuggest',
209 ],
210 // modules relating to functionality relating to watching an article
211 'watch' => [],
212 // modules which relate to the current users preferences
213 'user' => [],
214 // modules relating to RSS/Atom Feeds
215 'syndicate' => [],
216 ];
217
218 // Preload jquery.tablesorter for mediawiki.page.ready
219 if ( strpos( $out->getHTML(), 'sortable' ) !== false ) {
220 $modules['content'][] = 'jquery.tablesorter';
221 $modules['styles']['content'][] = 'jquery.tablesorter.styles';
222 }
223
224 // Preload jquery.makeCollapsible for mediawiki.page.ready
225 if ( strpos( $out->getHTML(), 'mw-collapsible' ) !== false ) {
226 $modules['content'][] = 'jquery.makeCollapsible';
227 $modules['styles']['content'][] = 'jquery.makeCollapsible.styles';
228 }
229
230 // Deprecated since 1.26: Unconditional loading of mediawiki.ui.button
231 // on every page is deprecated. Express a dependency instead.
232 if ( strpos( $out->getHTML(), 'mw-ui-button' ) !== false ) {
233 $modules['styles']['content'][] = 'mediawiki.ui.button';
234 }
235
236 if ( $out->isTOCEnabled() ) {
237 $modules['content'][] = 'mediawiki.toc';
238 $modules['styles']['content'][] = 'mediawiki.toc.styles';
239 }
240
241 // Add various resources if required
242 if ( $user->isLoggedIn()
243 && MediaWikiServices::getInstance()
244 ->getPermissionManager()
245 ->userHasAllRights( $user, 'writeapi', 'viewmywatchlist', 'editmywatchlist' )
246 && $this->getRelevantTitle()->canExist()
247 ) {
248 $modules['watch'][] = 'mediawiki.page.watch.ajax';
249 }
250
251 if ( $user->getBoolOption( 'editsectiononrightclick' ) ) {
252 $modules['user'][] = 'mediawiki.action.view.rightClickEdit';
253 }
254
255 // Crazy edit-on-double-click stuff
256 if ( $out->isArticle() && $user->getOption( 'editondblclick' ) ) {
257 $modules['user'][] = 'mediawiki.action.view.dblClickEdit';
258 }
259
260 if ( $out->isSyndicated() ) {
261 $modules['styles']['syndicate'][] = 'mediawiki.feedlink';
262 }
263
264 return $modules;
265 }
266
270 protected function preloadExistence() {
271 $titles = [];
272
273 // User/talk link
274 $user = $this->getUser();
275 if ( $user->isLoggedIn() ) {
276 $titles[] = $user->getUserPage();
277 $titles[] = $user->getTalkPage();
278 }
279
280 // Check, if the page can hold some kind of content, otherwise do nothing
281 $title = $this->getRelevantTitle();
282 if ( $title->canExist() && $title->canHaveTalkPage() ) {
283 if ( $title->isTalkPage() ) {
284 $titles[] = $title->getSubjectPage();
285 } else {
286 $titles[] = $title->getTalkPage();
287 }
288 }
289
290 // Footer links (used by SkinTemplate::prepareQuickTemplate)
291 foreach ( [
292 $this->footerLinkTitle( 'privacy', 'privacypage' ),
293 $this->footerLinkTitle( 'aboutsite', 'aboutpage' ),
294 $this->footerLinkTitle( 'disclaimers', 'disclaimerpage' ),
295 ] as $title ) {
296 if ( $title ) {
297 $titles[] = $title;
298 }
299 }
300
301 Hooks::run( 'SkinPreloadExistence', [ &$titles, $this ] );
302
303 if ( $titles ) {
304 $lb = new LinkBatch( $titles );
305 $lb->setCaller( __METHOD__ );
306 $lb->execute();
307 }
308 }
309
316 public function getRevisionId() {
317 return $this->getOutput()->getRevisionId();
318 }
319
326 public function isRevisionCurrent() {
327 return $this->getOutput()->isRevisionCurrent();
328 }
329
335 public function setRelevantTitle( $t ) {
336 $this->mRelevantTitle = $t;
337 }
338
349 public function getRelevantTitle() {
350 return $this->mRelevantTitle ?? $this->getTitle();
351 }
352
358 public function setRelevantUser( $u ) {
359 $this->mRelevantUser = $u;
360 }
361
370 public function getRelevantUser() {
371 if ( isset( $this->mRelevantUser ) ) {
372 return $this->mRelevantUser;
373 }
374 $title = $this->getRelevantTitle();
375 if ( $title->hasSubjectNamespace( NS_USER ) ) {
376 $rootUser = $title->getRootText();
377 if ( User::isIP( $rootUser ) ) {
378 $this->mRelevantUser = User::newFromName( $rootUser, false );
379 } else {
380 $user = User::newFromName( $rootUser, false );
381
382 if ( $user ) {
383 $user->load( User::READ_NORMAL );
384
385 if ( $user->isLoggedIn() ) {
386 $this->mRelevantUser = $user;
387 }
388 }
389 }
390 return $this->mRelevantUser;
391 }
392 return null;
393 }
394
398 abstract function outputPage();
399
405 public static function makeVariablesScript( $data, $nonce = null ) {
406 if ( $data ) {
407 return ResourceLoader::makeInlineScript(
408 ResourceLoader::makeConfigSetScript( $data ),
409 $nonce
410 );
411 }
412 return '';
413 }
414
421 public static function getDynamicStylesheetQuery() {
422 return [
423 'action' => 'raw',
424 'ctype' => 'text/css',
425 ];
426 }
427
434 public function setupSkinUserCss( OutputPage $out ) {
435 // Stub.
436 }
437
443 function getPageClasses( $title ) {
444 $numeric = 'ns-' . $title->getNamespace();
445 $user = $this->getUser();
446
447 if ( $title->isSpecialPage() ) {
448 $type = 'ns-special';
449 // T25315: provide a class based on the canonical special page name without subpages
450 list( $canonicalName ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
451 resolveAlias( $title->getDBkey() );
452 if ( $canonicalName ) {
453 $type .= ' ' . Sanitizer::escapeClass( "mw-special-$canonicalName" );
454 } else {
455 $type .= ' mw-invalidspecialpage';
456 }
457 } else {
458 if ( $title->isTalkPage() ) {
459 $type = 'ns-talk';
460 } else {
461 $type = 'ns-subject';
462 }
463 // T208315: add HTML class when the user can edit the page
464 if ( MediaWikiServices::getInstance()->getPermissionManager()
465 ->quickUserCan( 'edit', $user, $title )
466 ) {
467 $type .= ' mw-editable';
468 }
469 }
470
471 $name = Sanitizer::escapeClass( 'page-' . $title->getPrefixedText() );
472 $root = Sanitizer::escapeClass( 'rootpage-' . $title->getRootTitle()->getPrefixedText() );
473
474 return "$numeric $type $name $root";
475 }
476
481 public function getHtmlElementAttributes() {
482 $lang = $this->getLanguage();
483 return [
484 'lang' => $lang->getHtmlCode(),
485 'dir' => $lang->getDir(),
486 'class' => 'client-nojs',
487 ];
488 }
489
497 function addToBodyAttributes( $out, &$bodyAttrs ) {
498 // does nothing by default
499 }
500
505 function getLogo() {
506 return $this->getConfig()->get( 'Logo' );
507 }
508
518 public function shouldPreloadLogo() {
519 return false;
520 }
521
525 function getCategoryLinks() {
526 $out = $this->getOutput();
527 $allCats = $out->getCategoryLinks();
528 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
529
530 if ( $allCats === [] ) {
531 return '';
532 }
533
534 $embed = "<li>";
535 $pop = "</li>";
536
537 $s = '';
538 $colon = $this->msg( 'colon-separator' )->escaped();
539
540 if ( !empty( $allCats['normal'] ) ) {
541 $t = $embed . implode( $pop . $embed, $allCats['normal'] ) . $pop;
542
543 $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) );
544 $linkPage = $this->msg( 'pagecategorieslink' )->inContentLanguage()->text();
545 $title = Title::newFromText( $linkPage );
546 $link = $title ? $linkRenderer->makeLink( $title, $msg->text() ) : $msg->escaped();
547 $s .= '<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
548 $link . $colon . '<ul>' . $t . '</ul></div>';
549 }
550
551 # Hidden categories
552 if ( isset( $allCats['hidden'] ) ) {
553 if ( $this->getUser()->getBoolOption( 'showhiddencats' ) ) {
554 $class = ' mw-hidden-cats-user-shown';
555 } elseif ( $this->getTitle()->getNamespace() == NS_CATEGORY ) {
556 $class = ' mw-hidden-cats-ns-shown';
557 } else {
558 $class = ' mw-hidden-cats-hidden';
559 }
560
561 $s .= "<div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks$class\">" .
562 $this->msg( 'hidden-categories' )->numParams( count( $allCats['hidden'] ) )->escaped() .
563 $colon . '<ul>' . $embed . implode( $pop . $embed, $allCats['hidden'] ) . $pop . '</ul>' .
564 '</div>';
565 }
566
567 # optional 'dmoz-like' category browser. Will be shown under the list
568 # of categories an article belong to
569 if ( $this->getConfig()->get( 'UseCategoryBrowser' ) ) {
570 $s .= '<br /><hr />';
571
572 # get a big array of the parents tree
573 $parenttree = $this->getTitle()->getParentCategoryTree();
574 # Skin object passed by reference cause it can not be
575 # accessed under the method subfunction drawCategoryBrowser
576 $tempout = explode( "\n", $this->drawCategoryBrowser( $parenttree ) );
577 # Clean out bogus first entry and sort them
578 unset( $tempout[0] );
579 asort( $tempout );
580 # Output one per line
581 $s .= implode( "<br />\n", $tempout );
582 }
583
584 return $s;
585 }
586
592 function drawCategoryBrowser( $tree ) {
593 $return = '';
594 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
595
596 foreach ( $tree as $element => $parent ) {
597 if ( empty( $parent ) ) {
598 # element start a new list
599 $return .= "\n";
600 } else {
601 # grab the others elements
602 $return .= $this->drawCategoryBrowser( $parent ) . ' &gt; ';
603 }
604
605 # add our current element to the list
606 $eltitle = Title::newFromText( $element );
607 $return .= $linkRenderer->makeLink( $eltitle, $eltitle->getText() );
608 }
609
610 return $return;
611 }
612
616 function getCategories() {
617 $out = $this->getOutput();
618 $catlinks = $this->getCategoryLinks();
619
620 // Check what we're showing
621 $allCats = $out->getCategoryLinks();
622 $showHidden = $this->getUser()->getBoolOption( 'showhiddencats' ) ||
623 $this->getTitle()->getNamespace() == NS_CATEGORY;
624
625 $classes = [ 'catlinks' ];
626 if ( empty( $allCats['normal'] ) && !( !empty( $allCats['hidden'] ) && $showHidden ) ) {
627 $classes[] = 'catlinks-allhidden';
628 }
629
630 return Html::rawElement(
631 'div',
632 [ 'id' => 'catlinks', 'class' => $classes, 'data-mw' => 'interface' ],
633 $catlinks
634 );
635 }
636
651 protected function afterContentHook() {
652 $data = '';
653
654 if ( Hooks::run( 'SkinAfterContent', [ &$data, $this ] ) ) {
655 // adding just some spaces shouldn't toggle the output
656 // of the whole <div/>, so we use trim() here
657 if ( trim( $data ) != '' ) {
658 // Doing this here instead of in the skins to
659 // ensure that the div has the same ID in all
660 // skins
661 $data = "<div id='mw-data-after-content'>\n" .
662 "\t$data\n" .
663 "</div>\n";
664 }
665 } else {
666 wfDebug( "Hook SkinAfterContent changed output processing.\n" );
667 }
668
669 return $data;
670 }
671
677 protected function generateDebugHTML() {
678 return MWDebug::getHTMLDebugLog();
679 }
680
686 function bottomScripts() {
687 // TODO and the suckage continues. This function is really just a wrapper around
688 // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
689 // up at some point
690 $chunks = [ $this->getOutput()->getBottomScripts() ];
691
692 // Keep the hook appendage separate to preserve WrappedString objects.
693 // This enables BaseTemplate::getTrail() to merge them where possible.
694 $extraHtml = '';
695 Hooks::run( 'SkinAfterBottomScripts', [ $this, &$extraHtml ] );
696 if ( $extraHtml !== '' ) {
697 $chunks[] = $extraHtml;
698 }
699 return WrappedString::join( "\n", $chunks );
700 }
701
708 function printSource() {
709 $oldid = $this->getOutput()->getRevisionId();
710 if ( $oldid ) {
711 $canonicalUrl = $this->getTitle()->getCanonicalURL( 'oldid=' . $oldid );
712 $url = htmlspecialchars( wfExpandIRI( $canonicalUrl ) );
713 } else {
714 // oldid not available for non existing pages
715 $url = htmlspecialchars( wfExpandIRI( $this->getTitle()->getCanonicalURL() ) );
716 }
717
718 return $this->msg( 'retrievedfrom' )
719 ->rawParams( '<a dir="ltr" href="' . $url . '">' . $url . '</a>' )
720 ->parse();
721 }
722
726 function getUndeleteLink() {
727 $action = $this->getRequest()->getVal( 'action', 'view' );
728 $title = $this->getTitle();
729 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
730 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
731
732 if ( ( !$title->exists() || $action == 'history' ) &&
733 $permissionManager->quickUserCan( 'deletedhistory', $this->getUser(), $title )
734 ) {
735 $n = $title->isDeleted();
736
737 if ( $n ) {
738 if ( $permissionManager->quickUserCan( 'undelete',
739 $this->getUser(), $this->getTitle() )
740 ) {
741 $msg = 'thisisdeleted';
742 } else {
743 $msg = 'viewdeleted';
744 }
745
746 $subtitle = $this->msg( $msg )->rawParams(
747 $linkRenderer->makeKnownLink(
748 SpecialPage::getTitleFor( 'Undelete', $this->getTitle()->getPrefixedDBkey() ),
749 $this->msg( 'restorelink' )->numParams( $n )->text() )
750 )->escaped();
751
752 // Allow extensions to add more links
753 $links = [];
754 Hooks::run( 'UndeletePageToolLinks', [ $this->getContext(), $linkRenderer, &$links ] );
755
756 if ( $links ) {
757 $subtitle .= ''
758 . $this->msg( 'word-separator' )->escaped()
759 . $this->msg( 'parentheses' )
760 ->rawParams( $this->getLanguage()->pipeList( $links ) )
761 ->escaped();
762 }
763 return Html::rawElement( 'div', [ 'class' => 'mw-undelete-subtitle' ], $subtitle );
764 }
765 }
766
767 return '';
768 }
769
774 function subPageSubtitle( $out = null ) {
775 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
776 if ( $out === null ) {
777 $out = $this->getOutput();
778 }
779 $title = $out->getTitle();
780 $subpages = '';
781
782 if ( !Hooks::run( 'SkinSubPageSubtitle', [ &$subpages, $this, $out ] ) ) {
783 return $subpages;
784 }
785
786 if (
787 $out->isArticle() && MediaWikiServices::getInstance()->getNamespaceInfo()->
788 hasSubpages( $title->getNamespace() )
789 ) {
790 $ptext = $title->getPrefixedText();
791 if ( strpos( $ptext, '/' ) !== false ) {
792 $links = explode( '/', $ptext );
793 array_pop( $links );
794 $c = 0;
795 $growinglink = '';
796 $display = '';
797 $lang = $this->getLanguage();
798
799 foreach ( $links as $link ) {
800 $growinglink .= $link;
801 $display .= $link;
802 $linkObj = Title::newFromText( $growinglink );
803
804 if ( is_object( $linkObj ) && $linkObj->isKnown() ) {
805 $getlink = $linkRenderer->makeKnownLink(
806 $linkObj, $display
807 );
808
809 $c++;
810
811 if ( $c > 1 ) {
812 $subpages .= $lang->getDirMarkEntity() . $this->msg( 'pipe-separator' )->escaped();
813 } else {
814 $subpages .= '&lt; ';
815 }
816
817 $subpages .= $getlink;
818 $display = '';
819 } else {
820 $display .= '/';
821 }
822 $growinglink .= '/';
823 }
824 }
825 }
826
827 return $subpages;
828 }
829
833 function getSearchLink() {
834 $searchPage = SpecialPage::getTitleFor( 'Search' );
835 return $searchPage->getLocalURL();
836 }
837
842 function escapeSearchLink() {
843 wfDeprecated( __METHOD__, '1.34' );
844 return htmlspecialchars( $this->getSearchLink() );
845 }
846
851 function getCopyright( $type = 'detect' ) {
852 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
853 if ( $type == 'detect' ) {
854 if ( !$this->getOutput()->isRevisionCurrent()
855 && !$this->msg( 'history_copyright' )->inContentLanguage()->isDisabled()
856 ) {
857 $type = 'history';
858 } else {
859 $type = 'normal';
860 }
861 }
862
863 if ( $type == 'history' ) {
864 $msg = 'history_copyright';
865 } else {
866 $msg = 'copyright';
867 }
868
869 $config = $this->getConfig();
870
871 if ( $config->get( 'RightsPage' ) ) {
872 $title = Title::newFromText( $config->get( 'RightsPage' ) );
873 $link = $linkRenderer->makeKnownLink(
874 $title, new HtmlArmor( $config->get( 'RightsText' ) )
875 );
876 } elseif ( $config->get( 'RightsUrl' ) ) {
877 $link = Linker::makeExternalLink( $config->get( 'RightsUrl' ), $config->get( 'RightsText' ) );
878 } elseif ( $config->get( 'RightsText' ) ) {
879 $link = $config->get( 'RightsText' );
880 } else {
881 # Give up now
882 return '';
883 }
884
885 // Allow for site and per-namespace customization of copyright notice.
886 // @todo Remove deprecated $forContent param from hook handlers and then remove here.
887 $forContent = true;
888
889 Hooks::run(
890 'SkinCopyrightFooter',
891 [ $this->getTitle(), $type, &$msg, &$link, &$forContent ]
892 );
893
894 return $this->msg( $msg )->rawParams( $link )->text();
895 }
896
900 function getCopyrightIcon() {
901 $out = '';
902 $config = $this->getConfig();
903
904 $footerIcons = $config->get( 'FooterIcons' );
905 if ( $footerIcons['copyright']['copyright'] ) {
906 $out = $footerIcons['copyright']['copyright'];
907 } elseif ( $config->get( 'RightsIcon' ) ) {
908 $icon = htmlspecialchars( $config->get( 'RightsIcon' ) );
909 $url = $config->get( 'RightsUrl' );
910
911 if ( $url ) {
912 $out .= '<a href="' . htmlspecialchars( $url ) . '">';
913 }
914
915 $text = htmlspecialchars( $config->get( 'RightsText' ) );
916 $out .= "<img src=\"$icon\" alt=\"$text\" width=\"88\" height=\"31\" />";
917
918 if ( $url ) {
919 $out .= '</a>';
920 }
921 }
922
923 return $out;
924 }
925
930 function getPoweredBy() {
931 $resourceBasePath = $this->getConfig()->get( 'ResourceBasePath' );
932 $url1 = htmlspecialchars(
933 "$resourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
934 );
935 $url1_5 = htmlspecialchars(
936 "$resourceBasePath/resources/assets/poweredby_mediawiki_132x47.png"
937 );
938 $url2 = htmlspecialchars(
939 "$resourceBasePath/resources/assets/poweredby_mediawiki_176x62.png"
940 );
941 $text = '<a href="https://www.mediawiki.org/"><img src="' . $url1
942 . '" srcset="' . $url1_5 . ' 1.5x, ' . $url2 . ' 2x" '
943 . 'height="31" width="88" alt="Powered by MediaWiki" /></a>';
944 Hooks::run( 'SkinGetPoweredBy', [ &$text, $this ] );
945 return $text;
946 }
947
953 protected function lastModified() {
954 $timestamp = $this->getOutput()->getRevisionTimestamp();
955
956 # No cached timestamp, load it from the database
957 if ( $timestamp === null ) {
958 $timestamp = Revision::getTimestampFromId( $this->getTitle(),
959 $this->getOutput()->getRevisionId() );
960 }
961
962 if ( $timestamp ) {
963 $d = $this->getLanguage()->userDate( $timestamp, $this->getUser() );
964 $t = $this->getLanguage()->userTime( $timestamp, $this->getUser() );
965 $s = ' ' . $this->msg( 'lastmodifiedat', $d, $t )->parse();
966 } else {
967 $s = '';
968 }
969
970 if ( MediaWikiServices::getInstance()->getDBLoadBalancer()->getLaggedReplicaMode() ) {
971 $s .= ' <strong>' . $this->msg( 'laggedslavemode' )->parse() . '</strong>';
972 }
973
974 return $s;
975 }
976
981 function logoText( $align = '' ) {
982 if ( $align != '' ) {
983 $a = " style='float: {$align};'";
984 } else {
985 $a = '';
986 }
987
988 $mp = $this->msg( 'mainpage' )->escaped();
989 $mptitle = Title::newMainPage();
990 $url = ( is_object( $mptitle ) ? htmlspecialchars( $mptitle->getLocalURL() ) : '' );
991
992 $logourl = $this->getLogo();
993 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
994
995 return $s;
996 }
997
1006 function makeFooterIcon( $icon, $withImage = 'withImage' ) {
1007 if ( is_string( $icon ) ) {
1008 $html = $icon;
1009 } else { // Assuming array
1010 $url = $icon["url"] ?? null;
1011 unset( $icon["url"] );
1012 if ( isset( $icon["src"] ) && $withImage === 'withImage' ) {
1013 // do this the lazy way, just pass icon data as an attribute array
1014 $html = Html::element( 'img', $icon );
1015 } else {
1016 $html = htmlspecialchars( $icon["alt"] );
1017 }
1018 if ( $url ) {
1019 $html = Html::rawElement( 'a',
1020 [ "href" => $url, "target" => $this->getConfig()->get( 'ExternalLinkTarget' ) ],
1021 $html );
1022 }
1023 }
1024 return $html;
1025 }
1026
1031 function mainPageLink() {
1032 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1033 $s = $linkRenderer->makeKnownLink(
1034 Title::newMainPage(),
1035 $this->msg( 'mainpage' )->text()
1036 );
1037
1038 return $s;
1039 }
1040
1047 public function footerLink( $desc, $page ) {
1048 $title = $this->footerLinkTitle( $desc, $page );
1049 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1050 if ( !$title ) {
1051 return '';
1052 }
1053
1054 return $linkRenderer->makeKnownLink(
1055 $title,
1056 $this->msg( $desc )->text()
1057 );
1058 }
1059
1065 private function footerLinkTitle( $desc, $page ) {
1066 // If the link description has been set to "-" in the default language,
1067 if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
1068 // then it is disabled, for all languages.
1069 return null;
1070 }
1071 // Otherwise, we display the link for the user, described in their
1072 // language (which may or may not be the same as the default language),
1073 // but we make the link target be the one site-wide page.
1074 $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
1075
1076 return $title ?: null;
1077 }
1078
1083 function privacyLink() {
1084 return $this->footerLink( 'privacy', 'privacypage' );
1085 }
1086
1091 function aboutLink() {
1092 return $this->footerLink( 'aboutsite', 'aboutpage' );
1093 }
1094
1099 function disclaimerLink() {
1100 return $this->footerLink( 'disclaimers', 'disclaimerpage' );
1101 }
1102
1110 function editUrlOptions() {
1111 $options = [ 'action' => 'edit' ];
1112
1113 if ( !$this->getOutput()->isRevisionCurrent() ) {
1114 $options['oldid'] = intval( $this->getOutput()->getRevisionId() );
1115 }
1116
1117 return $options;
1118 }
1119
1124 function showEmailUser( $id ) {
1125 if ( $id instanceof User ) {
1126 $targetUser = $id;
1127 } else {
1128 $targetUser = User::newFromId( $id );
1129 }
1130
1131 # The sending user must have a confirmed email address and the receiving
1132 # user must accept emails from the sender.
1133 return $this->getUser()->canSendEmail()
1134 && SpecialEmailUser::validateTarget( $targetUser, $this->getUser() ) === '';
1135 }
1136
1148 function getSkinStylePath( $name ) {
1149 if ( $this->stylename === null ) {
1150 $class = static::class;
1151 throw new MWException( "$class::\$stylename must be set to use getSkinStylePath()" );
1152 }
1153
1154 return $this->getConfig()->get( 'StylePath' ) . "/{$this->stylename}/$name";
1155 }
1156
1157 /* these are used extensively in SkinTemplate, but also some other places */
1158
1163 static function makeMainPageUrl( $urlaction = '' ) {
1164 $title = Title::newMainPage();
1165 self::checkTitle( $title, '' );
1166
1167 return $title->getLinkURL( $urlaction );
1168 }
1169
1181 static function makeSpecialUrl( $name, $urlaction = '', $proto = null ) {
1182 $title = SpecialPage::getSafeTitleFor( $name );
1183 if ( is_null( $proto ) ) {
1184 return $title->getLocalURL( $urlaction );
1185 } else {
1186 return $title->getFullURL( $urlaction, false, $proto );
1187 }
1188 }
1189
1196 static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) {
1197 $title = SpecialPage::getSafeTitleFor( $name, $subpage );
1198 return $title->getLocalURL( $urlaction );
1199 }
1200
1206 static function makeI18nUrl( $name, $urlaction = '' ) {
1207 $title = Title::newFromText( wfMessage( $name )->inContentLanguage()->text() );
1208 self::checkTitle( $title, $name );
1209 return $title->getLocalURL( $urlaction );
1210 }
1211
1217 static function makeUrl( $name, $urlaction = '' ) {
1218 $title = Title::newFromText( $name );
1219 self::checkTitle( $title, $name );
1220
1221 return $title->getLocalURL( $urlaction );
1222 }
1223
1230 static function makeInternalOrExternalUrl( $name ) {
1231 if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $name ) ) {
1232 return $name;
1233 } else {
1234 return self::makeUrl( $name );
1235 }
1236 }
1237
1245 static function makeNSUrl( $name, $urlaction = '', $namespace = NS_MAIN ) {
1246 $title = Title::makeTitleSafe( $namespace, $name );
1247 self::checkTitle( $title, $name );
1248
1249 return $title->getLocalURL( $urlaction );
1250 }
1251
1258 static function makeUrlDetails( $name, $urlaction = '' ) {
1259 $title = Title::newFromText( $name );
1260 self::checkTitle( $title, $name );
1261
1262 return [
1263 'href' => $title->getLocalURL( $urlaction ),
1264 'exists' => $title->isKnown(),
1265 ];
1266 }
1267
1274 static function makeKnownUrlDetails( $name, $urlaction = '' ) {
1275 $title = Title::newFromText( $name );
1276 self::checkTitle( $title, $name );
1277
1278 return [
1279 'href' => $title->getLocalURL( $urlaction ),
1280 'exists' => true
1281 ];
1282 }
1283
1290 static function checkTitle( &$title, $name ) {
1291 if ( !is_object( $title ) ) {
1292 $title = Title::newFromText( $name );
1293 if ( !is_object( $title ) ) {
1294 $title = Title::newFromText( '--error: link target missing--' );
1295 }
1296 }
1297 }
1298
1320 public function buildSidebar() {
1321 $services = MediaWikiServices::getInstance();
1322 $callback = function ( $old = null, &$ttl = null ) {
1323 $bar = [];
1324 $this->addToSidebar( $bar, 'sidebar' );
1325 Hooks::run( 'SkinBuildSidebar', [ $this, &$bar ] );
1326 $msgCache = MediaWikiServices::getInstance()->getMessageCache();
1327 if ( $msgCache->isDisabled() ) {
1328 $ttl = WANObjectCache::TTL_UNCACHEABLE; // bug T133069
1329 }
1330
1331 return $bar;
1332 };
1333
1334 $msgCache = $services->getMessageCache();
1335 $wanCache = $services->getMainWANObjectCache();
1336 $config = $this->getConfig();
1337
1338 $sidebar = $config->get( 'EnableSidebarCache' )
1339 ? $wanCache->getWithSetCallback(
1340 $wanCache->makeKey( 'sidebar', $this->getLanguage()->getCode() ),
1341 $config->get( 'SidebarCacheExpiry' ),
1342 $callback,
1343 [
1344 'checkKeys' => [
1345 // Unless there is both no exact $code override nor an i18n definition
1346 // in the software, the only MediaWiki page to check is for $code.
1347 $msgCache->getCheckKey( $this->getLanguage()->getCode() )
1348 ],
1349 'lockTSE' => 30
1350 ]
1351 )
1352 : $callback();
1353
1354 // Apply post-processing to the cached value
1355 Hooks::run( 'SidebarBeforeOutput', [ $this, &$sidebar ] );
1356
1357 return $sidebar;
1358 }
1359
1369 public function addToSidebar( &$bar, $message ) {
1370 $this->addToSidebarPlain( $bar, $this->msg( $message )->inContentLanguage()->plain() );
1371 }
1372
1380 function addToSidebarPlain( &$bar, $text ) {
1381 $lines = explode( "\n", $text );
1382
1383 $heading = '';
1384 $config = $this->getConfig();
1385 $messageTitle = $config->get( 'EnableSidebarCache' )
1386 ? Title::newMainPage() : $this->getTitle();
1387
1388 foreach ( $lines as $line ) {
1389 if ( strpos( $line, '*' ) !== 0 ) {
1390 continue;
1391 }
1392 $line = rtrim( $line, "\r" ); // for Windows compat
1393
1394 if ( strpos( $line, '**' ) !== 0 ) {
1395 $heading = trim( $line, '* ' );
1396 if ( !array_key_exists( $heading, $bar ) ) {
1397 $bar[$heading] = [];
1398 }
1399 } else {
1400 $line = trim( $line, '* ' );
1401
1402 if ( strpos( $line, '|' ) !== false ) { // sanity check
1403 $line = MessageCache::singleton()->transform( $line, false, null, $messageTitle );
1404 $line = array_map( 'trim', explode( '|', $line, 2 ) );
1405 if ( count( $line ) !== 2 ) {
1406 // Second sanity check, could be hit by people doing
1407 // funky stuff with parserfuncs... (T35321)
1408 continue;
1409 }
1410
1411 $extraAttribs = [];
1412
1413 $msgLink = $this->msg( $line[0] )->title( $messageTitle )->inContentLanguage();
1414 if ( $msgLink->exists() ) {
1415 $link = $msgLink->text();
1416 if ( $link == '-' ) {
1417 continue;
1418 }
1419 } else {
1420 $link = $line[0];
1421 }
1422 $msgText = $this->msg( $line[1] )->title( $messageTitle );
1423 if ( $msgText->exists() ) {
1424 $text = $msgText->text();
1425 } else {
1426 $text = $line[1];
1427 }
1428
1429 if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $link ) ) {
1430 $href = $link;
1431
1432 // Parser::getExternalLinkAttribs won't work here because of the Namespace things
1433 if ( $config->get( 'NoFollowLinks' ) &&
1434 !wfMatchesDomainList( $href, $config->get( 'NoFollowDomainExceptions' ) )
1435 ) {
1436 $extraAttribs['rel'] = 'nofollow';
1437 }
1438
1439 if ( $config->get( 'ExternalLinkTarget' ) ) {
1440 $extraAttribs['target'] = $config->get( 'ExternalLinkTarget' );
1441 }
1442 } else {
1443 $title = Title::newFromText( $link );
1444
1445 if ( $title ) {
1446 $title = $title->fixSpecialName();
1447 $href = $title->getLinkURL();
1448 } else {
1449 $href = 'INVALID-TITLE';
1450 }
1451 }
1452
1453 $bar[$heading][] = array_merge( [
1454 'text' => $text,
1455 'href' => $href,
1456 'id' => Sanitizer::escapeIdForAttribute( 'n-' . strtr( $line[1], ' ', '-' ) ),
1457 'active' => false,
1458 ], $extraAttribs );
1459 } else {
1460 continue;
1461 }
1462 }
1463 }
1464
1465 return $bar;
1466 }
1467
1473 function getNewtalks() {
1474 $newMessagesAlert = '';
1475 $user = $this->getUser();
1476 $newtalks = $user->getNewMessageLinks();
1477 $out = $this->getOutput();
1478 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1479
1480 // Allow extensions to disable or modify the new messages alert
1481 if ( !Hooks::run( 'GetNewMessagesAlert', [ &$newMessagesAlert, $newtalks, $user, $out ] ) ) {
1482 return '';
1483 }
1484 if ( $newMessagesAlert ) {
1485 return $newMessagesAlert;
1486 }
1487
1488 if ( count( $newtalks ) == 1 && WikiMap::isCurrentWikiId( $newtalks[0]['wiki'] ) ) {
1489 $uTalkTitle = $user->getTalkPage();
1490 $lastSeenRev = $newtalks[0]['rev'] ?? null;
1491 $nofAuthors = 0;
1492 if ( $lastSeenRev !== null ) {
1493 $plural = true; // Default if we have a last seen revision: if unknown, use plural
1494 $latestRev = Revision::newFromTitle( $uTalkTitle, false, Revision::READ_NORMAL );
1495 if ( $latestRev !== null ) {
1496 // Singular if only 1 unseen revision, plural if several unseen revisions.
1497 $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
1498 $nofAuthors = $uTalkTitle->countAuthorsBetween(
1499 $lastSeenRev, $latestRev, 10, 'include_new' );
1500 }
1501 } else {
1502 // Singular if no revision -> diff link will show latest change only in any case
1503 $plural = false;
1504 }
1505 $plural = $plural ? 999 : 1;
1506 // 999 signifies "more than one revision". We don't know how many, and even if we did,
1507 // the number of revisions or authors is not necessarily the same as the number of
1508 // "messages".
1509 $newMessagesLink = $linkRenderer->makeKnownLink(
1510 $uTalkTitle,
1511 $this->msg( 'newmessageslinkplural' )->params( $plural )->text(),
1512 [],
1513 $uTalkTitle->isRedirect() ? [ 'redirect' => 'no' ] : []
1514 );
1515
1516 $newMessagesDiffLink = $linkRenderer->makeKnownLink(
1517 $uTalkTitle,
1518 $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->text(),
1519 [],
1520 $lastSeenRev !== null
1521 ? [ 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' ]
1522 : [ 'diff' => 'cur' ]
1523 );
1524
1525 if ( $nofAuthors >= 1 && $nofAuthors <= 10 ) {
1526 $newMessagesAlert = $this->msg(
1527 'youhavenewmessagesfromusers',
1528 $newMessagesLink,
1529 $newMessagesDiffLink
1530 )->numParams( $nofAuthors, $plural );
1531 } else {
1532 // $nofAuthors === 11 signifies "11 or more" ("more than 10")
1533 $newMessagesAlert = $this->msg(
1534 $nofAuthors > 10 ? 'youhavenewmessagesmanyusers' : 'youhavenewmessages',
1535 $newMessagesLink,
1536 $newMessagesDiffLink
1537 )->numParams( $plural );
1538 }
1539 $newMessagesAlert = $newMessagesAlert->text();
1540 # Disable CDN cache
1541 $out->setCdnMaxage( 0 );
1542 } elseif ( count( $newtalks ) ) {
1543 $sep = $this->msg( 'newtalkseparator' )->escaped();
1544 $msgs = [];
1545
1546 foreach ( $newtalks as $newtalk ) {
1547 $msgs[] = Xml::element(
1548 'a',
1549 [ 'href' => $newtalk['link'] ], $newtalk['wiki']
1550 );
1551 }
1552 $parts = implode( $sep, $msgs );
1553 $newMessagesAlert = $this->msg( 'youhavenewmessagesmulti' )->rawParams( $parts )->escaped();
1554 $out->setCdnMaxage( 0 );
1555 }
1556
1557 return $newMessagesAlert;
1558 }
1559
1567 private function getCachedNotice( $name ) {
1568 $config = $this->getConfig();
1569
1570 if ( $name === 'default' ) {
1571 // special case
1572 $notice = $config->get( 'SiteNotice' );
1573 if ( empty( $notice ) ) {
1574 return false;
1575 }
1576 } else {
1577 $msg = $this->msg( $name )->inContentLanguage();
1578 if ( $msg->isBlank() ) {
1579 return '';
1580 } elseif ( $msg->isDisabled() ) {
1581 return false;
1582 }
1583 $notice = $msg->plain();
1584 }
1585
1586 $services = MediaWikiServices::getInstance();
1587 $cache = $services->getMainWANObjectCache();
1588 $parsed = $cache->getWithSetCallback(
1589 // Use the extra hash appender to let eg SSL variants separately cache
1590 // Key is verified with md5 hash of unparsed wikitext
1591 $cache->makeKey( $name, $config->get( 'RenderHashAppend' ), md5( $notice ) ),
1592 // TTL in seconds
1593 600,
1594 function () use ( $notice ) {
1595 return $this->getOutput()->parseAsInterface( $notice );
1596 }
1597 );
1598
1599 $contLang = $services->getContentLanguage();
1600 return Html::rawElement(
1601 'div',
1602 [
1603 'id' => 'localNotice',
1604 'lang' => $contLang->getHtmlCode(),
1605 'dir' => $contLang->getDir()
1606 ],
1607 $parsed
1608 );
1609 }
1610
1616 function getSiteNotice() {
1617 $siteNotice = '';
1618
1619 if ( Hooks::run( 'SiteNoticeBefore', [ &$siteNotice, $this ] ) ) {
1620 if ( is_object( $this->getUser() ) && $this->getUser()->isLoggedIn() ) {
1621 $siteNotice = $this->getCachedNotice( 'sitenotice' );
1622 } else {
1623 $anonNotice = $this->getCachedNotice( 'anonnotice' );
1624 if ( $anonNotice === false ) {
1625 $siteNotice = $this->getCachedNotice( 'sitenotice' );
1626 } else {
1627 $siteNotice = $anonNotice;
1628 }
1629 }
1630 if ( $siteNotice === false ) {
1631 $siteNotice = $this->getCachedNotice( 'default' );
1632 }
1633 }
1634
1635 Hooks::run( 'SiteNoticeAfter', [ &$siteNotice, $this ] );
1636 return $siteNotice;
1637 }
1638
1652 public function doEditSectionLink( Title $nt, $section, $tooltip, Language $lang ) {
1653 // HTML generated here should probably have userlangattributes
1654 // added to it for LTR text on RTL pages
1655
1656 $attribs = [];
1657 if ( !is_null( $tooltip ) ) {
1658 $attribs['title'] = $this->msg( 'editsectionhint' )->rawParams( $tooltip )
1659 ->inLanguage( $lang )->text();
1660 }
1661
1662 $links = [
1663 'editsection' => [
1664 'text' => $this->msg( 'editsection' )->inLanguage( $lang )->text(),
1665 'targetTitle' => $nt,
1666 'attribs' => $attribs,
1667 'query' => [ 'action' => 'edit', 'section' => $section ]
1668 ]
1669 ];
1670
1671 Hooks::run( 'SkinEditSectionLinks', [ $this, $nt, $section, $tooltip, &$links, $lang ] );
1672
1673 $result = '<span class="mw-editsection"><span class="mw-editsection-bracket">[</span>';
1674
1675 $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1676 $linksHtml = [];
1677 foreach ( $links as $k => $linkDetails ) {
1678 $linksHtml[] = $linkRenderer->makeKnownLink(
1679 $linkDetails['targetTitle'],
1680 $linkDetails['text'],
1681 $linkDetails['attribs'],
1682 $linkDetails['query']
1683 );
1684 }
1685
1686 $result .= implode(
1687 '<span class="mw-editsection-divider">'
1688 . $this->msg( 'pipe-separator' )->inLanguage( $lang )->escaped()
1689 . '</span>',
1690 $linksHtml
1691 );
1692
1693 $result .= '<span class="mw-editsection-bracket">]</span></span>';
1694 return $result;
1695 }
1696
1697}
getPermissionManager()
getUser()
$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)
Throws a warning that $function is deprecated.
$fallback
getContext()
$line
Definition cdb.php:59
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.
Definition HtmlArmor.php:28
Internationalisation code.
Definition Language.php:37
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition LinkBatch.php:34
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
Definition Linker.php:848
MediaWiki exception.
MediaWikiServices is the service locator for the application scope of MediaWiki.
This is one of the Core classes and should be read at least once by any new developers.
static getTimestampFromId( $title, $id, $flags=0)
Get rev_timestamp from rev_id, without loading the rest of the row.
static newFromTitle(LinkTarget $linkTarget, $id=0, $flags=0)
Load either the current, or a specified, revision that's attached to a given link target.
Definition Revision.php:138
The main skin class which provides methods and properties for all other skins.
Definition Skin.php:38
aboutLink()
Gets the link to the wiki's about page.
Definition Skin.php:1091
isRevisionCurrent()
Whether the revision displayed is the latest revision of the page.
Definition Skin.php:326
static makeInternalOrExternalUrl( $name)
If url string starts with http, consider as external URL, else internal.
Definition Skin.php:1230
afterContentHook()
This runs a hook to allow extensions placing their stuff after content and article metadata (e....
Definition Skin.php:651
string $stylename
Stylesheets set to use.
Definition Skin.php:51
getNewtalks()
Gets new talk page messages for the current user and returns an appropriate alert message (or an empt...
Definition Skin.php:1473
mainPageLink()
Gets the link to the wiki's main page.
Definition Skin.php:1031
static getAllowedSkins()
Fetch the list of user-selectable skins in regards to $wgSkipSkins.
Definition Skin.php:83
doEditSectionLink(Title $nt, $section, $tooltip, Language $lang)
Create a section edit link.
Definition Skin.php:1652
getSkinStylePath( $name)
Return a fully resolved style path URL to images or styles stored in the current skin's folder.
Definition Skin.php:1148
getCachedNotice( $name)
Get a cached notice.
Definition Skin.php:1567
static makeMainPageUrl( $urlaction='')
Definition Skin.php:1163
static makeKnownUrlDetails( $name, $urlaction='')
Make URL details where the article exists (or at least it's convenient to think so)
Definition Skin.php:1274
generateDebugHTML()
Generate debug data HTML for displaying at the bottom of the main content area.
Definition Skin.php:677
getCopyrightIcon()
Definition Skin.php:900
privacyLink()
Gets the link to the wiki's privacy policy page.
Definition Skin.php:1083
footerLinkTitle( $desc, $page)
Definition Skin.php:1065
getSiteNotice()
Get the site notice.
Definition Skin.php:1616
getHtmlElementAttributes()
Return values for <html> element.
Definition Skin.php:481
static getSkinNames()
Fetch the set of available skins.
Definition Skin.php:57
static normalizeKey( $key)
Normalize a skin preference value to a form that can be loaded.
Definition Skin.php:104
getSkinName()
Definition Skin.php:158
getUndeleteLink()
Definition Skin.php:726
getPoweredBy()
Gets the powered by MediaWiki icon.
Definition Skin.php:930
outputPage()
Outputs the HTML generated by other functions.
getCategoryLinks()
Definition Skin.php:525
escapeSearchLink()
Definition Skin.php:842
static makeUrlDetails( $name, $urlaction='')
these return an array with the 'href' and boolean 'exists'
Definition Skin.php:1258
getLogo()
URL to the logo.
Definition Skin.php:505
$mRelevantTitle
Definition Skin.php:44
addToSidebar(&$bar, $message)
Add content from a sidebar system message Currently only used for MediaWiki:Sidebar (but may be used ...
Definition Skin.php:1369
static makeSpecialUrlSubpage( $name, $subpage, $urlaction='')
Definition Skin.php:1196
getRelevantUser()
Return the "relevant" user.
Definition Skin.php:370
setRelevantTitle( $t)
Set the "relevant" title.
Definition Skin.php:335
logoText( $align='')
Definition Skin.php:981
addToBodyAttributes( $out, &$bodyAttrs)
This will be called by OutputPage::headElement when it is creating the "<body>" tag,...
Definition Skin.php:497
$mRelevantUser
Definition Skin.php:45
drawCategoryBrowser( $tree)
Render the array as a series of links.
Definition Skin.php:592
static checkTitle(&$title, $name)
make sure we have some title to operate on
Definition Skin.php:1290
static makeUrl( $name, $urlaction='')
Definition Skin.php:1217
getPageClasses( $title)
TODO: document.
Definition Skin.php:443
getSearchLink()
Definition Skin.php:833
editUrlOptions()
Return URL options for the 'edit page' link.
Definition Skin.php:1110
showEmailUser( $id)
Definition Skin.php:1124
static makeNSUrl( $name, $urlaction='', $namespace=NS_MAIN)
this can be passed the NS number as defined in Language.php
Definition Skin.php:1245
buildSidebar()
Build an array that represents the sidebar(s), the navigation bar among them.
Definition Skin.php:1320
getCopyright( $type='detect')
Definition Skin.php:851
printSource()
Text with the permalink to the source page, usually shown on the footer of a printed page.
Definition Skin.php:708
shouldPreloadLogo()
Whether the logo should be preloaded with an HTTP link header or not.
Definition Skin.php:518
string null $skinname
Definition Skin.php:42
setRelevantUser( $u)
Set the "relevant" user.
Definition Skin.php:358
setupSkinUserCss(OutputPage $out)
Hook point for adding style modules to OutputPage.
Definition Skin.php:434
static getSkinNameMessages()
Fetch the skinname messages for available skins.
Definition Skin.php:67
makeFooterIcon( $icon, $withImage='withImage')
Renders a $wgFooterIcons icon according to the method's arguments.
Definition Skin.php:1006
getRevisionId()
Get the current revision ID.
Definition Skin.php:316
__construct( $skinname=null)
Definition Skin.php:149
preloadExistence()
Preload the existence of three commonly-requested pages in a single query.
Definition Skin.php:270
bottomScripts()
This gets called shortly before the "</body>" tag.
Definition Skin.php:686
disclaimerLink()
Gets the link to the wiki's general disclaimers page.
Definition Skin.php:1099
getDefaultModules()
Defines the ResourceLoader modules that should be added to the skin It is recommended that skins wish...
Definition Skin.php:179
static makeSpecialUrl( $name, $urlaction='', $proto=null)
Make a URL for a Special Page using the given query and protocol.
Definition Skin.php:1181
lastModified()
Get the timestamp of the latest revision, formatted in user language.
Definition Skin.php:953
static makeVariablesScript( $data, $nonce=null)
Definition Skin.php:405
initPage(OutputPage $out)
Definition Skin.php:165
static getDynamicStylesheetQuery()
Get the query to generate a dynamic stylesheet.
Definition Skin.php:421
subPageSubtitle( $out=null)
Definition Skin.php:774
addToSidebarPlain(&$bar, $text)
Add content from plain text.
Definition Skin.php:1380
footerLink( $desc, $page)
Returns an HTML link for use in the footer.
Definition Skin.php:1047
static makeI18nUrl( $name, $urlaction='')
Definition Skin.php:1206
getRelevantTitle()
Return the "relevant" title.
Definition Skin.php:349
getCategories()
Definition Skin.php:616
static validateTarget( $target, User $sender)
Validate target User.
Represents a title within MediaWiki.
Definition Title.php:42
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:51
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition User.php:518
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition User.php:542
static isIP( $name)
Does the string match an anonymous IP address?
Definition User.php:933
const NS_USER
Definition Defines.php:71
const NS_MAIN
Definition Defines.php:69
const NS_CATEGORY
Definition Defines.php:83
$cache
Definition mcc.php:33
$searchPage
$lines
Definition router.php:61
return true
Definition router.php:94
if(!isset( $args[0])) $lang