MediaWiki REL1_32
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 return SkinFactory::getDefaultInstance()->getSkinNames();
59 }
60
65 static function getSkinNameMessages() {
66 $messages = [];
67 foreach ( self::getSkinNames() as $skinKey => $skinName ) {
68 $messages[] = "skinname-$skinKey";
69 }
70 return $messages;
71 }
72
80 public static function getAllowedSkins() {
81 global $wgSkipSkins;
82
83 $allowedSkins = self::getSkinNames();
84
85 foreach ( $wgSkipSkins as $skip ) {
86 unset( $allowedSkins[$skip] );
87 }
88
89 return $allowedSkins;
90 }
91
101 static function normalizeKey( $key ) {
103
104 $skinNames = self::getSkinNames();
105
106 // Make keys lowercase for case-insensitive matching.
107 $skinNames = array_change_key_case( $skinNames, CASE_LOWER );
108 $key = strtolower( $key );
109 $defaultSkin = strtolower( $wgDefaultSkin );
110 $fallbackSkin = strtolower( $wgFallbackSkin );
111
112 if ( $key == '' || $key == 'default' ) {
113 // Don't return the default immediately;
114 // in a misconfiguration we need to fall back.
115 $key = $defaultSkin;
116 }
117
118 if ( isset( $skinNames[$key] ) ) {
119 return $key;
120 }
121
122 // Older versions of the software used a numeric setting
123 // in the user preferences.
124 $fallback = [
125 0 => $defaultSkin,
126 2 => 'cologneblue'
127 ];
128
129 if ( isset( $fallback[$key] ) ) {
130 $key = $fallback[$key];
131 }
132
133 if ( isset( $skinNames[$key] ) ) {
134 return $key;
135 } elseif ( isset( $skinNames[$defaultSkin] ) ) {
136 return $defaultSkin;
137 } else {
138 return $fallbackSkin;
139 }
140 }
141
146 public function __construct( $skinname = null ) {
147 if ( is_string( $skinname ) ) {
148 $this->skinname = $skinname;
149 }
150 }
151
155 public function getSkinName() {
156 return $this->skinname;
157 }
158
162 public function initPage( OutputPage $out ) {
163 $this->preloadExistence();
164 }
165
176 public function getDefaultModules() {
177 $out = $this->getOutput();
178 $config = $this->getConfig();
179 $user = $this->getUser();
180
181 // Modules declared in the $modules literal are loaded
182 // for ALL users, on ALL pages, in ALL skins.
183 // Keep this list as small as possible!
184 $modules = [
185 'styles' => [
186 // The 'styles' key sets render-blocking style modules
187 // Unlike other keys in $modules, this is an associative array
188 // where each key is its own group pointing to a list of modules
189 'core' => [
190 'mediawiki.legacy.shared',
191 'mediawiki.legacy.commonPrint',
192 ],
193 'content' => [],
194 'syndicate' => [],
195 ],
196 'core' => [
197 'site',
198 'mediawiki.page.startup',
199 'mediawiki.user',
200 ],
201 // modules that enhance the content in some way
202 'content' => [
203 'mediawiki.page.ready',
204 ],
205 // modules relating to search functionality
206 'search' => [],
207 // modules relating to functionality relating to watching an article
208 'watch' => [],
209 // modules which relate to the current users preferences
210 'user' => [],
211 // modules relating to RSS/Atom Feeds
212 'syndicate' => [],
213 ];
214
215 // Preload jquery.tablesorter for mediawiki.page.ready
216 if ( strpos( $out->getHTML(), 'sortable' ) !== false ) {
217 $modules['content'][] = 'jquery.tablesorter';
218 }
219
220 // Preload jquery.makeCollapsible for mediawiki.page.ready
221 if ( strpos( $out->getHTML(), 'mw-collapsible' ) !== false ) {
222 $modules['content'][] = 'jquery.makeCollapsible';
223 $modules['styles']['content'][] = 'jquery.makeCollapsible.styles';
224 }
225
226 // Deprecated since 1.26: Unconditional loading of mediawiki.ui.button
227 // on every page is deprecated. Express a dependency instead.
228 if ( strpos( $out->getHTML(), 'mw-ui-button' ) !== false ) {
229 $modules['styles']['content'][] = 'mediawiki.ui.button';
230 }
231
232 if ( $out->isTOCEnabled() ) {
233 $modules['content'][] = 'mediawiki.toc';
234 $modules['styles']['content'][] = 'mediawiki.toc.styles';
235 }
236
237 // Add various resources if required
238 if ( $user->isLoggedIn()
239 && $user->isAllowedAll( 'writeapi', 'viewmywatchlist', 'editmywatchlist' )
240 && $this->getRelevantTitle()->canExist()
241 ) {
242 $modules['watch'][] = 'mediawiki.page.watch.ajax';
243 }
244
245 $modules['search'][] = 'mediawiki.searchSuggest';
246
247 if ( $user->getBoolOption( 'editsectiononrightclick' ) ) {
248 $modules['user'][] = 'mediawiki.action.view.rightClickEdit';
249 }
250
251 // Crazy edit-on-double-click stuff
252 if ( $out->isArticle() && $user->getOption( 'editondblclick' ) ) {
253 $modules['user'][] = 'mediawiki.action.view.dblClickEdit';
254 }
255
256 if ( $out->isSyndicated() ) {
257 $modules['styles']['syndicate'][] = 'mediawiki.feedlink';
258 }
259
260 return $modules;
261 }
262
266 protected function preloadExistence() {
267 $titles = [];
268
269 // User/talk link
270 $user = $this->getUser();
271 if ( $user->isLoggedIn() ) {
272 $titles[] = $user->getUserPage();
273 $titles[] = $user->getTalkPage();
274 }
275
276 // Check, if the page can hold some kind of content, otherwise do nothing
277 $title = $this->getRelevantTitle();
278 if ( $title->canExist() ) {
279 if ( $title->isTalkPage() ) {
280 $titles[] = $title->getSubjectPage();
281 } else {
282 $titles[] = $title->getTalkPage();
283 }
284 }
285
286 // Footer links (used by SkinTemplate::prepareQuickTemplate)
287 foreach ( [
288 $this->footerLinkTitle( 'privacy', 'privacypage' ),
289 $this->footerLinkTitle( 'aboutsite', 'aboutpage' ),
290 $this->footerLinkTitle( 'disclaimers', 'disclaimerpage' ),
291 ] as $title ) {
292 if ( $title ) {
293 $titles[] = $title;
294 }
295 }
296
297 Hooks::run( 'SkinPreloadExistence', [ &$titles, $this ] );
298
299 if ( $titles ) {
300 $lb = new LinkBatch( $titles );
301 $lb->setCaller( __METHOD__ );
302 $lb->execute();
303 }
304 }
305
311 public function getRevisionId() {
312 return $this->getOutput()->getRevisionId();
313 }
314
320 public function isRevisionCurrent() {
321 $revID = $this->getRevisionId();
322 return $revID == 0 || $revID == $this->getTitle()->getLatestRevID();
323 }
324
330 public function setRelevantTitle( $t ) {
331 $this->mRelevantTitle = $t;
332 }
333
344 public function getRelevantTitle() {
345 if ( isset( $this->mRelevantTitle ) ) {
346 return $this->mRelevantTitle;
347 }
348 return $this->getTitle();
349 }
350
356 public function setRelevantUser( $u ) {
357 $this->mRelevantUser = $u;
358 }
359
368 public function getRelevantUser() {
369 if ( isset( $this->mRelevantUser ) ) {
370 return $this->mRelevantUser;
371 }
372 $title = $this->getRelevantTitle();
373 if ( $title->hasSubjectNamespace( NS_USER ) ) {
374 $rootUser = $title->getRootText();
375 if ( User::isIP( $rootUser ) ) {
376 $this->mRelevantUser = User::newFromName( $rootUser, false );
377 } else {
378 $user = User::newFromName( $rootUser, false );
379
380 if ( $user ) {
381 $user->load( User::READ_NORMAL );
382
383 if ( $user->isLoggedIn() ) {
384 $this->mRelevantUser = $user;
385 }
386 }
387 }
388 return $this->mRelevantUser;
389 }
390 return null;
391 }
392
397 abstract function outputPage( OutputPage $out = null );
398
404 public static function makeVariablesScript( $data, $nonce = null ) {
405 if ( $data ) {
408 $nonce
409 );
410 }
411 return '';
412 }
413
420 public static function getDynamicStylesheetQuery() {
421 return [
422 'action' => 'raw',
423 'ctype' => 'text/css',
424 ];
425 }
426
433 public function setupSkinUserCss( OutputPage $out ) {
434 // Stub.
435 }
436
442 function getPageClasses( $title ) {
443 $numeric = 'ns-' . $title->getNamespace();
444
445 if ( $title->isSpecialPage() ) {
446 $type = 'ns-special';
447 // T25315: provide a class based on the canonical special page name without subpages
448 list( $canonicalName ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
449 resolveAlias( $title->getDBkey() );
450 if ( $canonicalName ) {
451 $type .= ' ' . Sanitizer::escapeClass( "mw-special-$canonicalName" );
452 } else {
453 $type .= ' mw-invalidspecialpage';
454 }
455 } elseif ( $title->isTalkPage() ) {
456 $type = 'ns-talk';
457 } else {
458 $type = 'ns-subject';
459 }
460
461 $name = Sanitizer::escapeClass( 'page-' . $title->getPrefixedText() );
462 $root = Sanitizer::escapeClass( 'rootpage-' . $title->getRootTitle()->getPrefixedText() );
463
464 return "$numeric $type $name $root";
465 }
466
471 public function getHtmlElementAttributes() {
472 $lang = $this->getLanguage();
473 return [
474 'lang' => $lang->getHtmlCode(),
475 'dir' => $lang->getDir(),
476 'class' => 'client-nojs',
477 ];
478 }
479
487 function addToBodyAttributes( $out, &$bodyAttrs ) {
488 // does nothing by default
489 }
490
495 function getLogo() {
496 global $wgLogo;
497 return $wgLogo;
498 }
499
509 public function shouldPreloadLogo() {
510 return false;
511 }
512
516 function getCategoryLinks() {
518
519 $out = $this->getOutput();
520 $allCats = $out->getCategoryLinks();
521
522 if ( !count( $allCats ) ) {
523 return '';
524 }
525
526 $embed = "<li>";
527 $pop = "</li>";
528
529 $s = '';
530 $colon = $this->msg( 'colon-separator' )->escaped();
531
532 if ( !empty( $allCats['normal'] ) ) {
533 $t = $embed . implode( "{$pop}{$embed}", $allCats['normal'] ) . $pop;
534
535 $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) )->escaped();
536 $linkPage = $this->msg( 'pagecategorieslink' )->inContentLanguage()->text();
537 $title = Title::newFromText( $linkPage );
538 $link = $title ? Linker::link( $title, $msg ) : $msg;
539 $s .= '<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
540 $link . $colon . '<ul>' . $t . '</ul>' . '</div>';
541 }
542
543 # Hidden categories
544 if ( isset( $allCats['hidden'] ) ) {
545 if ( $this->getUser()->getBoolOption( 'showhiddencats' ) ) {
546 $class = ' mw-hidden-cats-user-shown';
547 } elseif ( $this->getTitle()->getNamespace() == NS_CATEGORY ) {
548 $class = ' mw-hidden-cats-ns-shown';
549 } else {
550 $class = ' mw-hidden-cats-hidden';
551 }
552
553 $s .= "<div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks$class\">" .
554 $this->msg( 'hidden-categories' )->numParams( count( $allCats['hidden'] ) )->escaped() .
555 $colon . '<ul>' . $embed . implode( "{$pop}{$embed}", $allCats['hidden'] ) . $pop . '</ul>' .
556 '</div>';
557 }
558
559 # optional 'dmoz-like' category browser. Will be shown under the list
560 # of categories an article belong to
561 if ( $wgUseCategoryBrowser ) {
562 $s .= '<br /><hr />';
563
564 # get a big array of the parents tree
565 $parenttree = $this->getTitle()->getParentCategoryTree();
566 # Skin object passed by reference cause it can not be
567 # accessed under the method subfunction drawCategoryBrowser
568 $tempout = explode( "\n", $this->drawCategoryBrowser( $parenttree ) );
569 # Clean out bogus first entry and sort them
570 unset( $tempout[0] );
571 asort( $tempout );
572 # Output one per line
573 $s .= implode( "<br />\n", $tempout );
574 }
575
576 return $s;
577 }
578
584 function drawCategoryBrowser( $tree ) {
585 $return = '';
586
587 foreach ( $tree as $element => $parent ) {
588 if ( empty( $parent ) ) {
589 # element start a new list
590 $return .= "\n";
591 } else {
592 # grab the others elements
593 $return .= $this->drawCategoryBrowser( $parent ) . ' &gt; ';
594 }
595
596 # add our current element to the list
597 $eltitle = Title::newFromText( $element );
598 $return .= Linker::link( $eltitle, htmlspecialchars( $eltitle->getText() ) );
599 }
600
601 return $return;
602 }
603
607 function getCategories() {
608 $out = $this->getOutput();
609 $catlinks = $this->getCategoryLinks();
610
611 // Check what we're showing
612 $allCats = $out->getCategoryLinks();
613 $showHidden = $this->getUser()->getBoolOption( 'showhiddencats' ) ||
614 $this->getTitle()->getNamespace() == NS_CATEGORY;
615
616 $classes = [ 'catlinks' ];
617 if ( empty( $allCats['normal'] ) && !( !empty( $allCats['hidden'] ) && $showHidden ) ) {
618 $classes[] = 'catlinks-allhidden';
619 }
620
621 return Html::rawElement(
622 'div',
623 [ 'id' => 'catlinks', 'class' => $classes, 'data-mw' => 'interface' ],
624 $catlinks
625 );
626 }
627
642 protected function afterContentHook() {
643 $data = '';
644
645 if ( Hooks::run( 'SkinAfterContent', [ &$data, $this ] ) ) {
646 // adding just some spaces shouldn't toggle the output
647 // of the whole <div/>, so we use trim() here
648 if ( trim( $data ) != '' ) {
649 // Doing this here instead of in the skins to
650 // ensure that the div has the same ID in all
651 // skins
652 $data = "<div id='mw-data-after-content'>\n" .
653 "\t$data\n" .
654 "</div>\n";
655 }
656 } else {
657 wfDebug( "Hook SkinAfterContent changed output processing.\n" );
658 }
659
660 return $data;
661 }
662
668 protected function generateDebugHTML() {
669 return MWDebug::getHTMLDebugLog();
670 }
671
677 function bottomScripts() {
678 // TODO and the suckage continues. This function is really just a wrapper around
679 // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
680 // up at some point
681 $chunks = [ $this->getOutput()->getBottomScripts() ];
682
683 // Keep the hook appendage separate to preserve WrappedString objects.
684 // This enables BaseTemplate::getTrail() to merge them where possible.
685 $extraHtml = '';
686 Hooks::run( 'SkinAfterBottomScripts', [ $this, &$extraHtml ] );
687 if ( $extraHtml !== '' ) {
688 $chunks[] = $extraHtml;
689 }
690 return WrappedString::join( "\n", $chunks );
691 }
692
699 function printSource() {
700 $oldid = $this->getRevisionId();
701 if ( $oldid ) {
702 $canonicalUrl = $this->getTitle()->getCanonicalURL( 'oldid=' . $oldid );
703 $url = htmlspecialchars( wfExpandIRI( $canonicalUrl ) );
704 } else {
705 // oldid not available for non existing pages
706 $url = htmlspecialchars( wfExpandIRI( $this->getTitle()->getCanonicalURL() ) );
707 }
708
709 return $this->msg( 'retrievedfrom' )
710 ->rawParams( '<a dir="ltr" href="' . $url . '">' . $url . '</a>' )
711 ->parse();
712 }
713
717 function getUndeleteLink() {
718 $action = $this->getRequest()->getVal( 'action', 'view' );
719
720 if ( $this->getTitle()->userCan( 'deletedhistory', $this->getUser() ) &&
721 ( !$this->getTitle()->exists() || $action == 'history' ) ) {
722 $n = $this->getTitle()->isDeleted();
723
724 if ( $n ) {
725 if ( $this->getTitle()->quickUserCan( 'undelete', $this->getUser() ) ) {
726 $msg = 'thisisdeleted';
727 } else {
728 $msg = 'viewdeleted';
729 }
730
731 return $this->msg( $msg )->rawParams(
733 SpecialPage::getTitleFor( 'Undelete', $this->getTitle()->getPrefixedDBkey() ),
734 $this->msg( 'restorelink' )->numParams( $n )->escaped() )
735 )->escaped();
736 }
737 }
738
739 return '';
740 }
741
746 function subPageSubtitle( $out = null ) {
747 if ( $out === null ) {
748 $out = $this->getOutput();
749 }
750 $title = $out->getTitle();
751 $subpages = '';
752
753 if ( !Hooks::run( 'SkinSubPageSubtitle', [ &$subpages, $this, $out ] ) ) {
754 return $subpages;
755 }
756
757 if ( $out->isArticle() && MWNamespace::hasSubpages( $title->getNamespace() ) ) {
758 $ptext = $title->getPrefixedText();
759 if ( strpos( $ptext, '/' ) !== false ) {
760 $links = explode( '/', $ptext );
761 array_pop( $links );
762 $c = 0;
763 $growinglink = '';
764 $display = '';
765 $lang = $this->getLanguage();
766
767 foreach ( $links as $link ) {
768 $growinglink .= $link;
769 $display .= $link;
770 $linkObj = Title::newFromText( $growinglink );
771
772 if ( is_object( $linkObj ) && $linkObj->isKnown() ) {
773 $getlink = Linker::linkKnown(
774 $linkObj,
775 htmlspecialchars( $display )
776 );
777
778 $c++;
779
780 if ( $c > 1 ) {
781 $subpages .= $lang->getDirMarkEntity() . $this->msg( 'pipe-separator' )->escaped();
782 } else {
783 $subpages .= '&lt; ';
784 }
785
786 $subpages .= $getlink;
787 $display = '';
788 } else {
789 $display .= '/';
790 }
791 $growinglink .= '/';
792 }
793 }
794 }
795
796 return $subpages;
797 }
798
802 function getSearchLink() {
803 $searchPage = SpecialPage::getTitleFor( 'Search' );
804 return $searchPage->getLocalURL();
805 }
806
810 function escapeSearchLink() {
811 return htmlspecialchars( $this->getSearchLink() );
812 }
813
818 function getCopyright( $type = 'detect' ) {
820
821 if ( $type == 'detect' ) {
822 if ( !$this->isRevisionCurrent()
823 && !$this->msg( 'history_copyright' )->inContentLanguage()->isDisabled()
824 ) {
825 $type = 'history';
826 } else {
827 $type = 'normal';
828 }
829 }
830
831 if ( $type == 'history' ) {
832 $msg = 'history_copyright';
833 } else {
834 $msg = 'copyright';
835 }
836
837 if ( $wgRightsPage ) {
838 $title = Title::newFromText( $wgRightsPage );
840 } elseif ( $wgRightsUrl ) {
842 } elseif ( $wgRightsText ) {
844 } else {
845 # Give up now
846 return '';
847 }
848
849 // Allow for site and per-namespace customization of copyright notice.
850 // @todo Remove deprecated $forContent param from hook handlers and then remove here.
851 $forContent = true;
852
853 Hooks::run(
854 'SkinCopyrightFooter',
855 [ $this->getTitle(), $type, &$msg, &$link, &$forContent ]
856 );
857
858 return $this->msg( $msg )->rawParams( $link )->text();
859 }
860
864 function getCopyrightIcon() {
866
867 $out = '';
868
869 if ( $wgFooterIcons['copyright']['copyright'] ) {
870 $out = $wgFooterIcons['copyright']['copyright'];
871 } elseif ( $wgRightsIcon ) {
872 $icon = htmlspecialchars( $wgRightsIcon );
873
874 if ( $wgRightsUrl ) {
875 $url = htmlspecialchars( $wgRightsUrl );
876 $out .= '<a href="' . $url . '">';
877 }
878
879 $text = htmlspecialchars( $wgRightsText );
880 $out .= "<img src=\"$icon\" alt=\"$text\" width=\"88\" height=\"31\" />";
881
882 if ( $wgRightsUrl ) {
883 $out .= '</a>';
884 }
885 }
886
887 return $out;
888 }
889
894 function getPoweredBy() {
895 global $wgResourceBasePath;
896
897 $url1 = htmlspecialchars(
898 "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
899 );
900 $url1_5 = htmlspecialchars(
901 "$wgResourceBasePath/resources/assets/poweredby_mediawiki_132x47.png"
902 );
903 $url2 = htmlspecialchars(
904 "$wgResourceBasePath/resources/assets/poweredby_mediawiki_176x62.png"
905 );
906 $text = '<a href="//www.mediawiki.org/"><img src="' . $url1
907 . '" srcset="' . $url1_5 . ' 1.5x, ' . $url2 . ' 2x" '
908 . 'height="31" width="88" alt="Powered by MediaWiki" /></a>';
909 Hooks::run( 'SkinGetPoweredBy', [ &$text, $this ] );
910 return $text;
911 }
912
918 protected function lastModified() {
919 $timestamp = $this->getOutput()->getRevisionTimestamp();
920
921 # No cached timestamp, load it from the database
922 if ( $timestamp === null ) {
923 $timestamp = Revision::getTimestampFromId( $this->getTitle(), $this->getRevisionId() );
924 }
925
926 if ( $timestamp ) {
927 $d = $this->getLanguage()->userDate( $timestamp, $this->getUser() );
928 $t = $this->getLanguage()->userTime( $timestamp, $this->getUser() );
929 $s = ' ' . $this->msg( 'lastmodifiedat', $d, $t )->parse();
930 } else {
931 $s = '';
932 }
933
934 if ( MediaWikiServices::getInstance()->getDBLoadBalancer()->getLaggedReplicaMode() ) {
935 $s .= ' <strong>' . $this->msg( 'laggedslavemode' )->parse() . '</strong>';
936 }
937
938 return $s;
939 }
940
945 function logoText( $align = '' ) {
946 if ( $align != '' ) {
947 $a = " style='float: {$align};'";
948 } else {
949 $a = '';
950 }
951
952 $mp = $this->msg( 'mainpage' )->escaped();
953 $mptitle = Title::newMainPage();
954 $url = ( is_object( $mptitle ) ? htmlspecialchars( $mptitle->getLocalURL() ) : '' );
955
956 $logourl = $this->getLogo();
957 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
958
959 return $s;
960 }
961
970 function makeFooterIcon( $icon, $withImage = 'withImage' ) {
971 if ( is_string( $icon ) ) {
972 $html = $icon;
973 } else { // Assuming array
974 $url = $icon["url"] ?? null;
975 unset( $icon["url"] );
976 if ( isset( $icon["src"] ) && $withImage === 'withImage' ) {
977 // do this the lazy way, just pass icon data as an attribute array
978 $html = Html::element( 'img', $icon );
979 } else {
980 $html = htmlspecialchars( $icon["alt"] );
981 }
982 if ( $url ) {
984 $html = Html::rawElement( 'a',
985 [ "href" => $url, "target" => $wgExternalLinkTarget ],
986 $html );
987 }
988 }
989 return $html;
990 }
991
996 function mainPageLink() {
998 Title::newMainPage(),
999 $this->msg( 'mainpage' )->escaped()
1000 );
1001
1002 return $s;
1003 }
1004
1011 public function footerLink( $desc, $page ) {
1012 $title = $this->footerLinkTitle( $desc, $page );
1013 if ( !$title ) {
1014 return '';
1015 }
1016
1017 return Linker::linkKnown(
1018 $title,
1019 $this->msg( $desc )->escaped()
1020 );
1021 }
1022
1028 private function footerLinkTitle( $desc, $page ) {
1029 // If the link description has been set to "-" in the default language,
1030 if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
1031 // then it is disabled, for all languages.
1032 return null;
1033 }
1034 // Otherwise, we display the link for the user, described in their
1035 // language (which may or may not be the same as the default language),
1036 // but we make the link target be the one site-wide page.
1037 $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
1038
1039 return $title ?: null;
1040 }
1041
1046 function privacyLink() {
1047 return $this->footerLink( 'privacy', 'privacypage' );
1048 }
1049
1054 function aboutLink() {
1055 return $this->footerLink( 'aboutsite', 'aboutpage' );
1056 }
1057
1062 function disclaimerLink() {
1063 return $this->footerLink( 'disclaimers', 'disclaimerpage' );
1064 }
1065
1073 function editUrlOptions() {
1074 $options = [ 'action' => 'edit' ];
1075
1076 if ( !$this->isRevisionCurrent() ) {
1077 $options['oldid'] = intval( $this->getRevisionId() );
1078 }
1079
1080 return $options;
1081 }
1082
1087 function showEmailUser( $id ) {
1088 if ( $id instanceof User ) {
1089 $targetUser = $id;
1090 } else {
1091 $targetUser = User::newFromId( $id );
1092 }
1093
1094 # The sending user must have a confirmed email address and the receiving
1095 # user must accept emails from the sender.
1096 return $this->getUser()->canSendEmail()
1097 && SpecialEmailUser::validateTarget( $targetUser, $this->getUser() ) === '';
1098 }
1099
1111 function getSkinStylePath( $name ) {
1112 global $wgStylePath;
1113
1114 if ( $this->stylename === null ) {
1115 $class = static::class;
1116 throw new MWException( "$class::\$stylename must be set to use getSkinStylePath()" );
1117 }
1118
1119 return "$wgStylePath/{$this->stylename}/$name";
1120 }
1121
1122 /* these are used extensively in SkinTemplate, but also some other places */
1123
1128 static function makeMainPageUrl( $urlaction = '' ) {
1129 $title = Title::newMainPage();
1130 self::checkTitle( $title, '' );
1131
1132 return $title->getLinkURL( $urlaction );
1133 }
1134
1146 static function makeSpecialUrl( $name, $urlaction = '', $proto = null ) {
1147 $title = SpecialPage::getSafeTitleFor( $name );
1148 if ( is_null( $proto ) ) {
1149 return $title->getLocalURL( $urlaction );
1150 } else {
1151 return $title->getFullURL( $urlaction, false, $proto );
1152 }
1153 }
1154
1161 static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) {
1162 $title = SpecialPage::getSafeTitleFor( $name, $subpage );
1163 return $title->getLocalURL( $urlaction );
1164 }
1165
1171 static function makeI18nUrl( $name, $urlaction = '' ) {
1172 $title = Title::newFromText( wfMessage( $name )->inContentLanguage()->text() );
1173 self::checkTitle( $title, $name );
1174 return $title->getLocalURL( $urlaction );
1175 }
1176
1182 static function makeUrl( $name, $urlaction = '' ) {
1183 $title = Title::newFromText( $name );
1184 self::checkTitle( $title, $name );
1185
1186 return $title->getLocalURL( $urlaction );
1187 }
1188
1195 static function makeInternalOrExternalUrl( $name ) {
1196 if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $name ) ) {
1197 return $name;
1198 } else {
1199 return self::makeUrl( $name );
1200 }
1201 }
1202
1210 static function makeNSUrl( $name, $urlaction = '', $namespace = NS_MAIN ) {
1211 $title = Title::makeTitleSafe( $namespace, $name );
1212 self::checkTitle( $title, $name );
1213
1214 return $title->getLocalURL( $urlaction );
1215 }
1216
1223 static function makeUrlDetails( $name, $urlaction = '' ) {
1224 $title = Title::newFromText( $name );
1225 self::checkTitle( $title, $name );
1226
1227 return [
1228 'href' => $title->getLocalURL( $urlaction ),
1229 'exists' => $title->isKnown(),
1230 ];
1231 }
1232
1239 static function makeKnownUrlDetails( $name, $urlaction = '' ) {
1240 $title = Title::newFromText( $name );
1241 self::checkTitle( $title, $name );
1242
1243 return [
1244 'href' => $title->getLocalURL( $urlaction ),
1245 'exists' => true
1246 ];
1247 }
1248
1255 static function checkTitle( &$title, $name ) {
1256 if ( !is_object( $title ) ) {
1257 $title = Title::newFromText( $name );
1258 if ( !is_object( $title ) ) {
1259 $title = Title::newFromText( '--error: link target missing--' );
1260 }
1261 }
1262 }
1263
1285 public function buildSidebar() {
1287
1288 $callback = function ( $old = null, &$ttl = null ) {
1289 $bar = [];
1290 $this->addToSidebar( $bar, 'sidebar' );
1291 Hooks::run( 'SkinBuildSidebar', [ $this, &$bar ] );
1292 if ( MessageCache::singleton()->isDisabled() ) {
1293 $ttl = WANObjectCache::TTL_UNCACHEABLE; // bug T133069
1294 }
1295
1296 return $bar;
1297 };
1298
1299 $msgCache = MessageCache::singleton();
1300 $wanCache = MediaWikiServices::getInstance()->getMainWANObjectCache();
1301
1302 $sidebar = $wgEnableSidebarCache
1303 ? $wanCache->getWithSetCallback(
1304 $wanCache->makeKey( 'sidebar', $this->getLanguage()->getCode() ),
1306 $callback,
1307 [
1308 'checkKeys' => [
1309 // Unless there is both no exact $code override nor an i18n definition
1310 // in the software, the only MediaWiki page to check is for $code.
1311 $msgCache->getCheckKey( $this->getLanguage()->getCode() )
1312 ],
1313 'lockTSE' => 30
1314 ]
1315 )
1316 : $callback();
1317
1318 // Apply post-processing to the cached value
1319 Hooks::run( 'SidebarBeforeOutput', [ $this, &$sidebar ] );
1320
1321 return $sidebar;
1322 }
1323
1333 public function addToSidebar( &$bar, $message ) {
1334 $this->addToSidebarPlain( $bar, $this->msg( $message )->inContentLanguage()->plain() );
1335 }
1336
1344 function addToSidebarPlain( &$bar, $text ) {
1345 $lines = explode( "\n", $text );
1346
1347 $heading = '';
1348 $messageTitle = $this->getConfig()->get( 'EnableSidebarCache' )
1349 ? Title::newMainPage() : $this->getTitle();
1350
1351 foreach ( $lines as $line ) {
1352 if ( strpos( $line, '*' ) !== 0 ) {
1353 continue;
1354 }
1355 $line = rtrim( $line, "\r" ); // for Windows compat
1356
1357 if ( strpos( $line, '**' ) !== 0 ) {
1358 $heading = trim( $line, '* ' );
1359 if ( !array_key_exists( $heading, $bar ) ) {
1360 $bar[$heading] = [];
1361 }
1362 } else {
1363 $line = trim( $line, '* ' );
1364
1365 if ( strpos( $line, '|' ) !== false ) { // sanity check
1366 $line = MessageCache::singleton()->transform( $line, false, null, $messageTitle );
1367 $line = array_map( 'trim', explode( '|', $line, 2 ) );
1368 if ( count( $line ) !== 2 ) {
1369 // Second sanity check, could be hit by people doing
1370 // funky stuff with parserfuncs... (T35321)
1371 continue;
1372 }
1373
1374 $extraAttribs = [];
1375
1376 $msgLink = $this->msg( $line[0] )->title( $messageTitle )->inContentLanguage();
1377 if ( $msgLink->exists() ) {
1378 $link = $msgLink->text();
1379 if ( $link == '-' ) {
1380 continue;
1381 }
1382 } else {
1383 $link = $line[0];
1384 }
1385 $msgText = $this->msg( $line[1] )->title( $messageTitle );
1386 if ( $msgText->exists() ) {
1387 $text = $msgText->text();
1388 } else {
1389 $text = $line[1];
1390 }
1391
1392 if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $link ) ) {
1393 $href = $link;
1394
1395 // Parser::getExternalLinkAttribs won't work here because of the Namespace things
1398 $extraAttribs['rel'] = 'nofollow';
1399 }
1400
1401 global $wgExternalLinkTarget;
1402 if ( $wgExternalLinkTarget ) {
1403 $extraAttribs['target'] = $wgExternalLinkTarget;
1404 }
1405 } else {
1406 $title = Title::newFromText( $link );
1407
1408 if ( $title ) {
1409 $title = $title->fixSpecialName();
1410 $href = $title->getLinkURL();
1411 } else {
1412 $href = 'INVALID-TITLE';
1413 }
1414 }
1415
1416 $bar[$heading][] = array_merge( [
1417 'text' => $text,
1418 'href' => $href,
1419 'id' => Sanitizer::escapeIdForAttribute( 'n-' . strtr( $line[1], ' ', '-' ) ),
1420 'active' => false,
1421 ], $extraAttribs );
1422 } else {
1423 continue;
1424 }
1425 }
1426 }
1427
1428 return $bar;
1429 }
1430
1436 function getNewtalks() {
1437 $newMessagesAlert = '';
1438 $user = $this->getUser();
1439 $newtalks = $user->getNewMessageLinks();
1440 $out = $this->getOutput();
1441
1442 // Allow extensions to disable or modify the new messages alert
1443 if ( !Hooks::run( 'GetNewMessagesAlert', [ &$newMessagesAlert, $newtalks, $user, $out ] ) ) {
1444 return '';
1445 }
1446 if ( $newMessagesAlert ) {
1447 return $newMessagesAlert;
1448 }
1449
1450 if ( count( $newtalks ) == 1 && $newtalks[0]['wiki'] === wfWikiID() ) {
1451 $uTalkTitle = $user->getTalkPage();
1452 $lastSeenRev = $newtalks[0]['rev'] ?? null;
1453 $nofAuthors = 0;
1454 if ( $lastSeenRev !== null ) {
1455 $plural = true; // Default if we have a last seen revision: if unknown, use plural
1456 $latestRev = Revision::newFromTitle( $uTalkTitle, false, Revision::READ_NORMAL );
1457 if ( $latestRev !== null ) {
1458 // Singular if only 1 unseen revision, plural if several unseen revisions.
1459 $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
1460 $nofAuthors = $uTalkTitle->countAuthorsBetween(
1461 $lastSeenRev, $latestRev, 10, 'include_new' );
1462 }
1463 } else {
1464 // Singular if no revision -> diff link will show latest change only in any case
1465 $plural = false;
1466 }
1467 $plural = $plural ? 999 : 1;
1468 // 999 signifies "more than one revision". We don't know how many, and even if we did,
1469 // the number of revisions or authors is not necessarily the same as the number of
1470 // "messages".
1471 $newMessagesLink = Linker::linkKnown(
1472 $uTalkTitle,
1473 $this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
1474 [],
1475 $uTalkTitle->isRedirect() ? [ 'redirect' => 'no' ] : []
1476 );
1477
1478 $newMessagesDiffLink = Linker::linkKnown(
1479 $uTalkTitle,
1480 $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->escaped(),
1481 [],
1482 $lastSeenRev !== null
1483 ? [ 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' ]
1484 : [ 'diff' => 'cur' ]
1485 );
1486
1487 if ( $nofAuthors >= 1 && $nofAuthors <= 10 ) {
1488 $newMessagesAlert = $this->msg(
1489 'youhavenewmessagesfromusers',
1490 $newMessagesLink,
1491 $newMessagesDiffLink
1492 )->numParams( $nofAuthors, $plural );
1493 } else {
1494 // $nofAuthors === 11 signifies "11 or more" ("more than 10")
1495 $newMessagesAlert = $this->msg(
1496 $nofAuthors > 10 ? 'youhavenewmessagesmanyusers' : 'youhavenewmessages',
1497 $newMessagesLink,
1498 $newMessagesDiffLink
1499 )->numParams( $plural );
1500 }
1501 $newMessagesAlert = $newMessagesAlert->text();
1502 # Disable CDN cache
1503 $out->setCdnMaxage( 0 );
1504 } elseif ( count( $newtalks ) ) {
1505 $sep = $this->msg( 'newtalkseparator' )->escaped();
1506 $msgs = [];
1507
1508 foreach ( $newtalks as $newtalk ) {
1509 $msgs[] = Xml::element(
1510 'a',
1511 [ 'href' => $newtalk['link'] ], $newtalk['wiki']
1512 );
1513 }
1514 $parts = implode( $sep, $msgs );
1515 $newMessagesAlert = $this->msg( 'youhavenewmessagesmulti' )->rawParams( $parts )->escaped();
1516 $out->setCdnMaxage( 0 );
1517 }
1518
1519 return $newMessagesAlert;
1520 }
1521
1529 private function getCachedNotice( $name ) {
1530 global $wgRenderHashAppend;
1531
1532 $needParse = false;
1533
1534 if ( $name === 'default' ) {
1535 // special case
1536 global $wgSiteNotice;
1537 $notice = $wgSiteNotice;
1538 if ( empty( $notice ) ) {
1539 return false;
1540 }
1541 } else {
1542 $msg = $this->msg( $name )->inContentLanguage();
1543 if ( $msg->isBlank() ) {
1544 return '';
1545 } elseif ( $msg->isDisabled() ) {
1546 return false;
1547 }
1548 $notice = $msg->plain();
1549 }
1550
1551 $services = MediaWikiServices::getInstance();
1552 $cache = $services->getMainWANObjectCache();
1553 $parsed = $cache->getWithSetCallback(
1554 // Use the extra hash appender to let eg SSL variants separately cache
1555 // Key is verified with md5 hash of unparsed wikitext
1556 $cache->makeKey( $name, $wgRenderHashAppend, md5( $notice ) ),
1557 // TTL in seconds
1558 600,
1559 function () use ( $notice ) {
1560 return $this->getOutput()->parse( $notice );
1561 }
1562 );
1563
1564 $contLang = $services->getContentLanguage();
1565 return Html::rawElement(
1566 'div',
1567 [
1568 'id' => 'localNotice',
1569 'lang' => $contLang->getHtmlCode(),
1570 'dir' => $contLang->getDir()
1571 ],
1572 $parsed
1573 );
1574 }
1575
1581 function getSiteNotice() {
1582 $siteNotice = '';
1583
1584 if ( Hooks::run( 'SiteNoticeBefore', [ &$siteNotice, $this ] ) ) {
1585 if ( is_object( $this->getUser() ) && $this->getUser()->isLoggedIn() ) {
1586 $siteNotice = $this->getCachedNotice( 'sitenotice' );
1587 } else {
1588 $anonNotice = $this->getCachedNotice( 'anonnotice' );
1589 if ( $anonNotice === false ) {
1590 $siteNotice = $this->getCachedNotice( 'sitenotice' );
1591 } else {
1592 $siteNotice = $anonNotice;
1593 }
1594 }
1595 if ( $siteNotice === false ) {
1596 $siteNotice = $this->getCachedNotice( 'default' );
1597 }
1598 }
1599
1600 Hooks::run( 'SiteNoticeAfter', [ &$siteNotice, $this ] );
1601 return $siteNotice;
1602 }
1603
1619 public function doEditSectionLink( Title $nt, $section, $tooltip = null, $lang = false ) {
1620 // HTML generated here should probably have userlangattributes
1621 // added to it for LTR text on RTL pages
1622
1623 if ( !$lang instanceof Language ) {
1624 wfDeprecated( __METHOD__ . ' with other type than Language for $lang', '1.32' );
1626 }
1627
1628 $attribs = [];
1629 if ( !is_null( $tooltip ) ) {
1630 $attribs['title'] = $this->msg( 'editsectionhint' )->rawParams( $tooltip )
1631 ->inLanguage( $lang )->text();
1632 }
1633
1634 $links = [
1635 'editsection' => [
1636 'text' => $this->msg( 'editsection' )->inLanguage( $lang )->escaped(),
1637 'targetTitle' => $nt,
1638 'attribs' => $attribs,
1639 'query' => [ 'action' => 'edit', 'section' => $section ],
1640 'options' => [ 'noclasses', 'known' ]
1641 ]
1642 ];
1643
1644 Hooks::run( 'SkinEditSectionLinks', [ $this, $nt, $section, $tooltip, &$links, $lang ] );
1645
1646 $result = '<span class="mw-editsection"><span class="mw-editsection-bracket">[</span>';
1647
1648 $linksHtml = [];
1649 foreach ( $links as $k => $linkDetails ) {
1650 $linksHtml[] = Linker::link(
1651 $linkDetails['targetTitle'],
1652 $linkDetails['text'],
1653 $linkDetails['attribs'],
1654 $linkDetails['query'],
1655 $linkDetails['options']
1656 );
1657 }
1658
1659 $result .= implode(
1660 '<span class="mw-editsection-divider">'
1661 . $this->msg( 'pipe-separator' )->inLanguage( $lang )->escaped()
1662 . '</span>',
1663 $linksHtml
1664 );
1665
1666 $result .= '<span class="mw-editsection-bracket">]</span></span>';
1667 return $result;
1668 }
1669
1670}
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
This list may contain false positives That usually means there is additional text with links below the first Each row contains links to the first and second as well as the first line of the second redirect text
$wgRightsIcon
Override for copyright metadata.
$wgRightsUrl
Set this to specify an external URL containing details about the content license used on your wiki.
$wgRenderHashAppend
Append a configured value to the parser cache and the sitenotice key so that they can be kept separat...
$wgFallbackSkin
Fallback skin used when the skin defined by $wgDefaultSkin can't be found.
$wgNoFollowLinks
If true, external URL links in wiki text will be given the rel="nofollow" attribute as a hint to sear...
$wgSiteNotice
Site notice shown at the top of each page.
$wgRightsText
If either $wgRightsUrl or $wgRightsPage is specified then this variable gives the text for the link.
$wgResourceBasePath
The default 'remoteBasePath' value for instances of ResourceLoaderFileModule.
$wgSidebarCacheExpiry
Expiry time for the sidebar cache, in seconds.
$wgFooterIcons
Abstract list of footer icons for skins in place of old copyrightico and poweredbyico code You can ad...
$wgEnableSidebarCache
If on, the sidebar navigation links are cached for users with the current language set.
$wgNoFollowDomainExceptions
If this is set to an array of domains, external links to these domain names (or any subdomains) will ...
$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.
$wgUseCategoryBrowser
Use experimental, DMOZ-like category browser.
$wgExternalLinkTarget
Set a default target for external links, e.g.
$wgStylePath
The URL path of the skins directory.
$wgLogo
The URL path of the wiki logo.
$wgRightsPage
Override for copyright metadata.
wfGetLangObj( $langcode=false)
Return a Language object from $langcode.
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.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
wfWikiID()
Get an ASCII string identifying this wiki This is used as a prefix in memcached keys.
$messages
$fallback
$line
Definition cdb.php:59
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
msg( $key)
Get a Message object with context set Parameters are the same as wfMessage()
Internationalisation code.
Definition Language.php:35
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition LinkBatch.php:34
static link( $target, $html=null, $customAttribs=[], $query=[], $options=[])
This function returns an HTML link to the given target.
Definition Linker.php:84
static linkKnown( $target, $html=null, $customAttribs=[], $query=[], $options=[ 'known'])
Identical to link(), except $options defaults to 'known'.
Definition Linker.php:141
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
Definition Linker.php:826
MediaWiki exception.
MediaWikiServices is the service locator for the application scope of MediaWiki.
This class should be covered by a general architecture document which does not exist as of January 20...
static makeInlineScript( $script, $nonce=null)
Returns an HTML script tag that runs given JS code after startup and base modules.
static makeConfigSetScript(array $configuration)
Returns JS code which will set the MediaWiki configuration array to the given value.
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:133
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:1054
isRevisionCurrent()
Whether the revision displayed is the latest revision of the page.
Definition Skin.php:320
static makeInternalOrExternalUrl( $name)
If url string starts with http, consider as external URL, else internal.
Definition Skin.php:1195
afterContentHook()
This runs a hook to allow extensions placing their stuff after content and article metadata (e....
Definition Skin.php:642
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:1436
mainPageLink()
Gets the link to the wiki's main page.
Definition Skin.php:996
static getAllowedSkins()
Fetch the list of user-selectable skins in regards to $wgSkipSkins.
Definition Skin.php:80
getSkinStylePath( $name)
Return a fully resolved style path URL to images or styles stored in the current skin's folder.
Definition Skin.php:1111
getCachedNotice( $name)
Get a cached notice.
Definition Skin.php:1529
static makeMainPageUrl( $urlaction='')
Definition Skin.php:1128
static makeKnownUrlDetails( $name, $urlaction='')
Make URL details where the article exists (or at least it's convenient to think so)
Definition Skin.php:1239
generateDebugHTML()
Generate debug data HTML for displaying at the bottom of the main content area.
Definition Skin.php:668
getCopyrightIcon()
Definition Skin.php:864
privacyLink()
Gets the link to the wiki's privacy policy page.
Definition Skin.php:1046
footerLinkTitle( $desc, $page)
Definition Skin.php:1028
getSiteNotice()
Get the site notice.
Definition Skin.php:1581
getHtmlElementAttributes()
Return values for <html> element.
Definition Skin.php:471
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:101
getSkinName()
Definition Skin.php:155
getUndeleteLink()
Definition Skin.php:717
getPoweredBy()
Gets the powered by MediaWiki icon.
Definition Skin.php:894
getCategoryLinks()
Definition Skin.php:516
escapeSearchLink()
Definition Skin.php:810
static makeUrlDetails( $name, $urlaction='')
these return an array with the 'href' and boolean 'exists'
Definition Skin.php:1223
getLogo()
URL to the logo.
Definition Skin.php:495
$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:1333
static makeSpecialUrlSubpage( $name, $subpage, $urlaction='')
Definition Skin.php:1161
getRelevantUser()
Return the "relevant" user.
Definition Skin.php:368
setRelevantTitle( $t)
Set the "relevant" title.
Definition Skin.php:330
logoText( $align='')
Definition Skin.php:945
addToBodyAttributes( $out, &$bodyAttrs)
This will be called by OutputPage::headElement when it is creating the "<body>" tag,...
Definition Skin.php:487
$mRelevantUser
Definition Skin.php:45
drawCategoryBrowser( $tree)
Render the array as a series of links.
Definition Skin.php:584
static checkTitle(&$title, $name)
make sure we have some title to operate on
Definition Skin.php:1255
static makeUrl( $name, $urlaction='')
Definition Skin.php:1182
getPageClasses( $title)
TODO: document.
Definition Skin.php:442
getSearchLink()
Definition Skin.php:802
editUrlOptions()
Return URL options for the 'edit page' link.
Definition Skin.php:1073
showEmailUser( $id)
Definition Skin.php:1087
static makeNSUrl( $name, $urlaction='', $namespace=NS_MAIN)
this can be passed the NS number as defined in Language.php
Definition Skin.php:1210
buildSidebar()
Build an array that represents the sidebar(s), the navigation bar among them.
Definition Skin.php:1285
getCopyright( $type='detect')
Definition Skin.php:818
printSource()
Text with the permalink to the source page, usually shown on the footer of a printed page.
Definition Skin.php:699
shouldPreloadLogo()
Whether the logo should be preloaded with an HTTP link header or not.
Definition Skin.php:509
string null $skinname
Definition Skin.php:42
setRelevantUser( $u)
Set the "relevant" user.
Definition Skin.php:356
setupSkinUserCss(OutputPage $out)
Hook point for adding style modules to OutputPage.
Definition Skin.php:433
static getSkinNameMessages()
Fetch the skinname messages for available skins.
Definition Skin.php:65
makeFooterIcon( $icon, $withImage='withImage')
Renders a $wgFooterIcons icon according to the method's arguments.
Definition Skin.php:970
getRevisionId()
Get the current revision ID.
Definition Skin.php:311
__construct( $skinname=null)
Definition Skin.php:146
preloadExistence()
Preload the existence of three commonly-requested pages in a single query.
Definition Skin.php:266
bottomScripts()
This gets called shortly before the "</body>" tag.
Definition Skin.php:677
outputPage(OutputPage $out=null)
Outputs the HTML generated by other functions.
doEditSectionLink(Title $nt, $section, $tooltip=null, $lang=false)
Create a section edit link.
Definition Skin.php:1619
disclaimerLink()
Gets the link to the wiki's general disclaimers page.
Definition Skin.php:1062
getDefaultModules()
Defines the ResourceLoader modules that should be added to the skin It is recommended that skins wish...
Definition Skin.php:176
static makeSpecialUrl( $name, $urlaction='', $proto=null)
Make a URL for a Special Page using the given query and protocol.
Definition Skin.php:1146
lastModified()
Get the timestamp of the latest revision, formatted in user language.
Definition Skin.php:918
static makeVariablesScript( $data, $nonce=null)
Definition Skin.php:404
initPage(OutputPage $out)
Definition Skin.php:162
static getDynamicStylesheetQuery()
Get the query to generate a dynamic stylesheet.
Definition Skin.php:420
subPageSubtitle( $out=null)
Definition Skin.php:746
addToSidebarPlain(&$bar, $text)
Add content from plain text.
Definition Skin.php:1344
footerLink( $desc, $page)
Returns an HTML link for use in the footer.
Definition Skin.php:1011
static makeI18nUrl( $name, $urlaction='')
Definition Skin.php:1171
getRelevantTitle()
Return the "relevant" title.
Definition Skin.php:344
getCategories()
Definition Skin.php:607
static validateTarget( $target, User $sender=null)
Validate target User.
Represents a title within MediaWiki.
Definition Title.php:39
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:47
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition User.php:592
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition User.php:615
static isIP( $name)
Does the string match an anonymous IP address?
Definition User.php:971
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition deferred.txt:11
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
const NS_USER
Definition Defines.php:66
const NS_MAIN
Definition Defines.php:64
const NS_CATEGORY
Definition Defines.php:78
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImgAuthModifyHeaders':Executed just before a file is streamed to a user via img_auth.php, allowing headers to be modified beforehand. $title:LinkTarget object & $headers:HTTP headers(name=> value, names are case insensitive). Two headers get special handling:If-Modified-Since(value must be a valid HTTP date) and Range(must be of the form "bytes=(\d*-\d*)") will be honored when streaming the file. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. Return false to stop further processing of the tag $reader:XMLReader object $logInfo:Array of information 'ImportHandlePageXMLTag':When parsing a XML tag in a page. Return false to stop further processing of the tag $reader:XMLReader object & $pageInfo:Array of information 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. Return false to stop further processing of the tag $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. Return false to stop further processing of the tag $reader:XMLReader object 'ImportHandleUnknownUser':When a user doesn 't exist locally, this hook is called to give extensions an opportunity to auto-create it. If the auto-creation is successful, return false. $name:User name 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. Return false to stop further processing of the tag $reader:XMLReader object $revisionInfo:Array of information 'ImportLogInterwikiLink':Hook to change the interwiki link used in log entries and edit summaries for transwiki imports. & $fullInterwikiPrefix:Interwiki prefix, may contain colons. & $pageTitle:String that contains page title. 'ImportSources':Called when reading from the $wgImportSources configuration variable. Can be used to lazy-load the import sources list. & $importSources:The value of $wgImportSources. Modify as necessary. See the comment in DefaultSettings.php for the detail of how to structure this array. 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. & $title:Title object for the current page & $request:WebRequest & $ignoreRedirect:boolean to skip redirect check & $target:Title/string of redirect target & $article:Article object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) & $article:article(object) being checked 'IsTrustedProxy':Override the result of IP::isTrustedProxy() & $ip:IP being check & $result:Change this value to override the result of IP::isTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of Sanitizer::validateEmail(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetMagic':DEPRECATED since 1.16! Use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language & $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetSpecialPageAliases':DEPRECATED! Use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language & $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code:language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Array with elements of the form "language:title" in the order that they will be output. & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LanguageSelector':Hook to change the language selector available on a page. $out:The output page. $cssClassName:CSS class name of the language selector. 'LinkBegin':DEPRECATED since 1.28! Use HtmlPageLinkRendererBegin instead. Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition hooks.txt:2042
either a plain
Definition hooks.txt:2105
the value of this variable comes from LanguageConverter indexed by page_id indexed by prefixed DB keys on which the links will be shown can modify can modify can modify this should be populated with an alert message to that effect $newtalks
Definition hooks.txt:1764
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition hooks.txt:2050
namespace and then decline to actually register it file or subcat img or subcat $title
Definition hooks.txt:994
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition hooks.txt:2055
static configuration should be added through ResourceLoaderGetConfigVars instead can be used to get the real title e g db for database replication lag or jobqueue for job queue size converted to pseudo seconds It is possible to add more fields and they will be returned to the user in the API response after the basic globals have been set but before ordinary actions take place or wrap services the preferred way to define a new service is the $wgServiceWiringFiles array $services
Definition hooks.txt:2335
either a unescaped string or a HtmlArmor object after in associative array form externallinks including delete and has completed for all link tables whether this was an auto creation use $formDescriptor instead default is conds Array Extra conditions for the No matching items in log is displayed if loglist is empty msgKey Array If you want a nice box with a set this to the key of the message First element is the message additional optional elements are parameters for the key that are processed with wfMessage() -> params() ->parseAsBlock() - offset Set to overwrite offset parameter in $wgRequest set to '' to unset offset - wrap String Wrap the message in html(usually something like "&lt;div ...>$1&lt;/div>"). - flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException':Called before an exception(or PHP error) is logged. This is meant for integration with external error aggregation services
this hook is for auditing only or null if authentication failed before getting that far or null if we can t even determine that probably a stub it is not rendered in wiki pages or galleries in category pages allow injecting custom HTML after the section Any uses of the hook need to handle escaping see BaseTemplate::getToolbox and BaseTemplate::makeListItem for details on the format of individual items inside of this array or by returning and letting standard HTTP rendering take place modifiable or by returning false and taking over the output $out
Definition hooks.txt:894
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition hooks.txt:2062
usually copyright or history_copyright This message must be in HTML not wikitext & $link
Definition hooks.txt:3106
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:302
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing & $attribs
Definition hooks.txt:2063
usually copyright or history_copyright This message must be in HTML not wikitext if the section is included from a template $section
Definition hooks.txt:3107
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account $user
Definition hooks.txt:247
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition injection.txt:37
linkcache txt The LinkCache class maintains a list of article titles and the information about whether or not the article exists in the database This is used to mark up links when displaying a page If the same link appears more than once on any page then it only has to be looked up once In most cases link lookups are done in batches with the LinkBatch class or the equivalent in so the link cache is mostly useful for short snippets of parsed and for links in the navigation areas of the skin The link cache was formerly used to track links used in a document for the purposes of updating the link tables This application is now deprecated To create a you can use the following $titles
Definition linkcache.txt:17
$cache
Definition mcc.php:33
$searchPage
$parent
$lines
Definition router.php:61
if(!isset( $args[0])) $lang