MediaWiki REL1_30
Skin.php
Go to the documentation of this file.
1<?php
24
36abstract class Skin extends ContextSource {
37 protected $skinname = null;
38 protected $mRelevantTitle = null;
39 protected $mRelevantUser = null;
40
45 public $stylename = null;
46
51 static function getSkinNames() {
52 return SkinFactory::getDefaultInstance()->getSkinNames();
53 }
54
59 static function getSkinNameMessages() {
60 $messages = [];
61 foreach ( self::getSkinNames() as $skinKey => $skinName ) {
62 $messages[] = "skinname-$skinKey";
63 }
64 return $messages;
65 }
66
74 public static function getAllowedSkins() {
76
77 $allowedSkins = self::getSkinNames();
78
79 foreach ( $wgSkipSkins as $skip ) {
80 unset( $allowedSkins[$skip] );
81 }
82
83 return $allowedSkins;
84 }
85
95 static function normalizeKey( $key ) {
97
98 $skinNames = self::getSkinNames();
99
100 // Make keys lowercase for case-insensitive matching.
101 $skinNames = array_change_key_case( $skinNames, CASE_LOWER );
102 $key = strtolower( $key );
103 $defaultSkin = strtolower( $wgDefaultSkin );
104 $fallbackSkin = strtolower( $wgFallbackSkin );
105
106 if ( $key == '' || $key == 'default' ) {
107 // Don't return the default immediately;
108 // in a misconfiguration we need to fall back.
109 $key = $defaultSkin;
110 }
111
112 if ( isset( $skinNames[$key] ) ) {
113 return $key;
114 }
115
116 // Older versions of the software used a numeric setting
117 // in the user preferences.
118 $fallback = [
119 0 => $defaultSkin,
120 2 => 'cologneblue'
121 ];
122
123 if ( isset( $fallback[$key] ) ) {
124 $key = $fallback[$key];
125 }
126
127 if ( isset( $skinNames[$key] ) ) {
128 return $key;
129 } elseif ( isset( $skinNames[$defaultSkin] ) ) {
130 return $defaultSkin;
131 } else {
132 return $fallbackSkin;
133 }
134 }
135
139 public function getSkinName() {
140 return $this->skinname;
141 }
142
146 public function initPage( OutputPage $out ) {
147 $this->preloadExistence();
148 }
149
159 public function getDefaultModules() {
161
162 $out = $this->getOutput();
163 $config = $this->getConfig();
164 $user = $out->getUser();
165 $modules = [
166 // modules not specific to any specific skin or page
167 'core' => [
168 // Enforce various default modules for all pages and all skins
169 // Keep this list as small as possible
170 'site',
171 'mediawiki.page.startup',
172 'mediawiki.user',
173 ],
174 // modules that enhance the page content in some way
175 'content' => [
176 'mediawiki.page.ready',
177 ],
178 // modules relating to search functionality
179 'search' => [],
180 // modules relating to functionality relating to watching an article
181 'watch' => [],
182 // modules which relate to the current users preferences
183 'user' => [],
184 ];
185
186 // Support for high-density display images if enabled
187 if ( $config->get( 'ResponsiveImages' ) ) {
188 $modules['core'][] = 'mediawiki.hidpi';
189 }
190
191 // Preload jquery.tablesorter for mediawiki.page.ready
192 if ( strpos( $out->getHTML(), 'sortable' ) !== false ) {
193 $modules['content'][] = 'jquery.tablesorter';
194 }
195
196 // Preload jquery.makeCollapsible for mediawiki.page.ready
197 if ( strpos( $out->getHTML(), 'mw-collapsible' ) !== false ) {
198 $modules['content'][] = 'jquery.makeCollapsible';
199 }
200
201 if ( $out->isTOCEnabled() ) {
202 $modules['content'][] = 'mediawiki.toc';
203 }
204
205 // Add various resources if required
206 if ( $wgUseAjax && $wgEnableAPI ) {
207 if ( $wgEnableWriteAPI && $user->isLoggedIn()
208 && $user->isAllowedAll( 'writeapi', 'viewmywatchlist', 'editmywatchlist' )
209 && $this->getRelevantTitle()->canExist()
210 ) {
211 $modules['watch'][] = 'mediawiki.page.watch.ajax';
212 }
213
214 $modules['search'][] = 'mediawiki.searchSuggest';
215 }
216
217 if ( $user->getBoolOption( 'editsectiononrightclick' ) ) {
218 $modules['user'][] = 'mediawiki.action.view.rightClickEdit';
219 }
220
221 // Crazy edit-on-double-click stuff
222 if ( $out->isArticle() && $user->getOption( 'editondblclick' ) ) {
223 $modules['user'][] = 'mediawiki.action.view.dblClickEdit';
224 }
225 return $modules;
226 }
227
231 protected function preloadExistence() {
232 $titles = [];
233
234 // User/talk link
235 $user = $this->getUser();
236 if ( $user->isLoggedIn() ) {
237 $titles[] = $user->getUserPage();
238 $titles[] = $user->getTalkPage();
239 }
240
241 // Check, if the page can hold some kind of content, otherwise do nothing
242 $title = $this->getRelevantTitle();
243 if ( $title->canExist() ) {
244 if ( $title->isTalkPage() ) {
245 $titles[] = $title->getSubjectPage();
246 } else {
247 $titles[] = $title->getTalkPage();
248 }
249 }
250
251 // Footer links (used by SkinTemplate::prepareQuickTemplate)
252 foreach ( [
253 $this->footerLinkTitle( 'privacy', 'privacypage' ),
254 $this->footerLinkTitle( 'aboutsite', 'aboutpage' ),
255 $this->footerLinkTitle( 'disclaimers', 'disclaimerpage' ),
256 ] as $title ) {
257 if ( $title ) {
258 $titles[] = $title;
259 }
260 }
261
262 Hooks::run( 'SkinPreloadExistence', [ &$titles, $this ] );
263
264 if ( $titles ) {
265 $lb = new LinkBatch( $titles );
266 $lb->setCaller( __METHOD__ );
267 $lb->execute();
268 }
269 }
270
276 public function getRevisionId() {
277 return $this->getOutput()->getRevisionId();
278 }
279
285 public function isRevisionCurrent() {
286 $revID = $this->getRevisionId();
287 return $revID == 0 || $revID == $this->getTitle()->getLatestRevID();
288 }
289
295 public function setRelevantTitle( $t ) {
296 $this->mRelevantTitle = $t;
297 }
298
309 public function getRelevantTitle() {
310 if ( isset( $this->mRelevantTitle ) ) {
312 }
313 return $this->getTitle();
314 }
315
321 public function setRelevantUser( $u ) {
322 $this->mRelevantUser = $u;
323 }
324
333 public function getRelevantUser() {
334 if ( isset( $this->mRelevantUser ) ) {
336 }
337 $title = $this->getRelevantTitle();
338 if ( $title->hasSubjectNamespace( NS_USER ) ) {
339 $rootUser = $title->getRootText();
340 if ( User::isIP( $rootUser ) ) {
341 $this->mRelevantUser = User::newFromName( $rootUser, false );
342 } else {
343 $user = User::newFromName( $rootUser, false );
344
345 if ( $user ) {
346 $user->load( User::READ_NORMAL );
347
348 if ( $user->isLoggedIn() ) {
349 $this->mRelevantUser = $user;
350 }
351 }
352 }
354 }
355 return null;
356 }
357
362 abstract function outputPage( OutputPage $out = null );
363
368 static function makeVariablesScript( $data ) {
369 if ( $data ) {
372 );
373 } else {
374 return '';
375 }
376 }
377
383 public static function getDynamicStylesheetQuery() {
385
386 return [
387 'action' => 'raw',
388 'maxage' => $wgSquidMaxage,
389 'usemsgcache' => 'yes',
390 'ctype' => 'text/css',
391 'smaxage' => $wgSquidMaxage,
392 ];
393 }
394
403 abstract function setupSkinUserCss( OutputPage $out );
404
410 function getPageClasses( $title ) {
411 $numeric = 'ns-' . $title->getNamespace();
412
413 if ( $title->isSpecialPage() ) {
414 $type = 'ns-special';
415 // T25315: provide a class based on the canonical special page name without subpages
416 list( $canonicalName ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
417 if ( $canonicalName ) {
418 $type .= ' ' . Sanitizer::escapeClass( "mw-special-$canonicalName" );
419 } else {
420 $type .= ' mw-invalidspecialpage';
421 }
422 } elseif ( $title->isTalkPage() ) {
423 $type = 'ns-talk';
424 } else {
425 $type = 'ns-subject';
426 }
427
428 $name = Sanitizer::escapeClass( 'page-' . $title->getPrefixedText() );
429 $root = Sanitizer::escapeClass( 'rootpage-' . $title->getRootTitle()->getPrefixedText() );
430
431 return "$numeric $type $name $root";
432 }
433
438 public function getHtmlElementAttributes() {
439 $lang = $this->getLanguage();
440 return [
441 'lang' => $lang->getHtmlCode(),
442 'dir' => $lang->getDir(),
443 'class' => 'client-nojs',
444 ];
445 }
446
454 function addToBodyAttributes( $out, &$bodyAttrs ) {
455 // does nothing by default
456 }
457
462 function getLogo() {
464 return $wgLogo;
465 }
466
472 public function shouldPreloadLogo() {
473 return false;
474 }
475
479 function getCategoryLinks() {
481
482 $out = $this->getOutput();
483 $allCats = $out->getCategoryLinks();
484
485 if ( !count( $allCats ) ) {
486 return '';
487 }
488
489 $embed = "<li>";
490 $pop = "</li>";
491
492 $s = '';
493 $colon = $this->msg( 'colon-separator' )->escaped();
494
495 if ( !empty( $allCats['normal'] ) ) {
496 $t = $embed . implode( "{$pop}{$embed}", $allCats['normal'] ) . $pop;
497
498 $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) )->escaped();
499 $linkPage = wfMessage( 'pagecategorieslink' )->inContentLanguage()->text();
500 $title = Title::newFromText( $linkPage );
501 $link = $title ? Linker::link( $title, $msg ) : $msg;
502 $s .= '<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
503 $link . $colon . '<ul>' . $t . '</ul>' . '</div>';
504 }
505
506 # Hidden categories
507 if ( isset( $allCats['hidden'] ) ) {
508 if ( $this->getUser()->getBoolOption( 'showhiddencats' ) ) {
509 $class = ' mw-hidden-cats-user-shown';
510 } elseif ( $this->getTitle()->getNamespace() == NS_CATEGORY ) {
511 $class = ' mw-hidden-cats-ns-shown';
512 } else {
513 $class = ' mw-hidden-cats-hidden';
514 }
515
516 $s .= "<div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks$class\">" .
517 $this->msg( 'hidden-categories' )->numParams( count( $allCats['hidden'] ) )->escaped() .
518 $colon . '<ul>' . $embed . implode( "{$pop}{$embed}", $allCats['hidden'] ) . $pop . '</ul>' .
519 '</div>';
520 }
521
522 # optional 'dmoz-like' category browser. Will be shown under the list
523 # of categories an article belong to
524 if ( $wgUseCategoryBrowser ) {
525 $s .= '<br /><hr />';
526
527 # get a big array of the parents tree
528 $parenttree = $this->getTitle()->getParentCategoryTree();
529 # Skin object passed by reference cause it can not be
530 # accessed under the method subfunction drawCategoryBrowser
531 $tempout = explode( "\n", $this->drawCategoryBrowser( $parenttree ) );
532 # Clean out bogus first entry and sort them
533 unset( $tempout[0] );
534 asort( $tempout );
535 # Output one per line
536 $s .= implode( "<br />\n", $tempout );
537 }
538
539 return $s;
540 }
541
547 function drawCategoryBrowser( $tree ) {
548 $return = '';
549
550 foreach ( $tree as $element => $parent ) {
551 if ( empty( $parent ) ) {
552 # element start a new list
553 $return .= "\n";
554 } else {
555 # grab the others elements
556 $return .= $this->drawCategoryBrowser( $parent ) . ' &gt; ';
557 }
558
559 # add our current element to the list
560 $eltitle = Title::newFromText( $element );
561 $return .= Linker::link( $eltitle, htmlspecialchars( $eltitle->getText() ) );
562 }
563
564 return $return;
565 }
566
570 function getCategories() {
571 $out = $this->getOutput();
572 $catlinks = $this->getCategoryLinks();
573
574 // Check what we're showing
575 $allCats = $out->getCategoryLinks();
576 $showHidden = $this->getUser()->getBoolOption( 'showhiddencats' ) ||
577 $this->getTitle()->getNamespace() == NS_CATEGORY;
578
579 $classes = [ 'catlinks' ];
580 if ( empty( $allCats['normal'] ) && !( !empty( $allCats['hidden'] ) && $showHidden ) ) {
581 $classes[] = 'catlinks-allhidden';
582 }
583
584 return Html::rawElement(
585 'div',
586 [ 'id' => 'catlinks', 'class' => $classes, 'data-mw' => 'interface' ],
587 $catlinks
588 );
589 }
590
605 protected function afterContentHook() {
606 $data = '';
607
608 if ( Hooks::run( 'SkinAfterContent', [ &$data, $this ] ) ) {
609 // adding just some spaces shouldn't toggle the output
610 // of the whole <div/>, so we use trim() here
611 if ( trim( $data ) != '' ) {
612 // Doing this here instead of in the skins to
613 // ensure that the div has the same ID in all
614 // skins
615 $data = "<div id='mw-data-after-content'>\n" .
616 "\t$data\n" .
617 "</div>\n";
618 }
619 } else {
620 wfDebug( "Hook SkinAfterContent changed output processing.\n" );
621 }
622
623 return $data;
624 }
625
631 protected function generateDebugHTML() {
632 return MWDebug::getHTMLDebugLog();
633 }
634
640 function bottomScripts() {
641 // TODO and the suckage continues. This function is really just a wrapper around
642 // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
643 // up at some point
644 $bottomScriptText = $this->getOutput()->getBottomScripts();
645 Hooks::run( 'SkinAfterBottomScripts', [ $this, &$bottomScriptText ] );
646
647 return $bottomScriptText;
648 }
649
656 function printSource() {
657 $oldid = $this->getRevisionId();
658 if ( $oldid ) {
659 $canonicalUrl = $this->getTitle()->getCanonicalURL( 'oldid=' . $oldid );
660 $url = htmlspecialchars( wfExpandIRI( $canonicalUrl ) );
661 } else {
662 // oldid not available for non existing pages
663 $url = htmlspecialchars( wfExpandIRI( $this->getTitle()->getCanonicalURL() ) );
664 }
665
666 return $this->msg( 'retrievedfrom' )
667 ->rawParams( '<a dir="ltr" href="' . $url . '">' . $url . '</a>' )
668 ->parse();
669 }
670
674 function getUndeleteLink() {
675 $action = $this->getRequest()->getVal( 'action', 'view' );
676
677 if ( $this->getTitle()->userCan( 'deletedhistory', $this->getUser() ) &&
678 ( !$this->getTitle()->exists() || $action == 'history' ) ) {
679 $n = $this->getTitle()->isDeleted();
680
681 if ( $n ) {
682 if ( $this->getTitle()->quickUserCan( 'undelete', $this->getUser() ) ) {
683 $msg = 'thisisdeleted';
684 } else {
685 $msg = 'viewdeleted';
686 }
687
688 return $this->msg( $msg )->rawParams(
690 SpecialPage::getTitleFor( 'Undelete', $this->getTitle()->getPrefixedDBkey() ),
691 $this->msg( 'restorelink' )->numParams( $n )->escaped() )
692 )->escaped();
693 }
694 }
695
696 return '';
697 }
698
703 function subPageSubtitle( $out = null ) {
704 if ( $out === null ) {
705 $out = $this->getOutput();
706 }
707 $title = $out->getTitle();
708 $subpages = '';
709
710 if ( !Hooks::run( 'SkinSubPageSubtitle', [ &$subpages, $this, $out ] ) ) {
711 return $subpages;
712 }
713
714 if ( $out->isArticle() && MWNamespace::hasSubpages( $title->getNamespace() ) ) {
715 $ptext = $title->getPrefixedText();
716 if ( strpos( $ptext, '/' ) !== false ) {
717 $links = explode( '/', $ptext );
718 array_pop( $links );
719 $c = 0;
720 $growinglink = '';
721 $display = '';
722 $lang = $this->getLanguage();
723
724 foreach ( $links as $link ) {
725 $growinglink .= $link;
726 $display .= $link;
727 $linkObj = Title::newFromText( $growinglink );
728
729 if ( is_object( $linkObj ) && $linkObj->isKnown() ) {
730 $getlink = Linker::linkKnown(
731 $linkObj,
732 htmlspecialchars( $display )
733 );
734
735 $c++;
736
737 if ( $c > 1 ) {
738 $subpages .= $lang->getDirMarkEntity() . $this->msg( 'pipe-separator' )->escaped();
739 } else {
740 $subpages .= '&lt; ';
741 }
742
743 $subpages .= $getlink;
744 $display = '';
745 } else {
746 $display .= '/';
747 }
748 $growinglink .= '/';
749 }
750 }
751 }
752
753 return $subpages;
754 }
755
760 function showIPinHeader() {
761 wfDeprecated( __METHOD__, '1.27' );
762 return false;
763 }
764
768 function getSearchLink() {
770 return $searchPage->getLocalURL();
771 }
772
776 function escapeSearchLink() {
777 return htmlspecialchars( $this->getSearchLink() );
778 }
779
784 function getCopyright( $type = 'detect' ) {
786
787 if ( $type == 'detect' ) {
788 if ( !$this->isRevisionCurrent()
789 && !$this->msg( 'history_copyright' )->inContentLanguage()->isDisabled()
790 ) {
791 $type = 'history';
792 } else {
793 $type = 'normal';
794 }
795 }
796
797 if ( $type == 'history' ) {
798 $msg = 'history_copyright';
799 } else {
800 $msg = 'copyright';
801 }
802
803 if ( $wgRightsPage ) {
804 $title = Title::newFromText( $wgRightsPage );
806 } elseif ( $wgRightsUrl ) {
808 } elseif ( $wgRightsText ) {
810 } else {
811 # Give up now
812 return '';
813 }
814
815 // Allow for site and per-namespace customization of copyright notice.
816 // @todo Remove deprecated $forContent param from hook handlers and then remove here.
817 $forContent = true;
818
819 Hooks::run(
820 'SkinCopyrightFooter',
821 [ $this->getTitle(), $type, &$msg, &$link, &$forContent ]
822 );
823
824 return $this->msg( $msg )->rawParams( $link )->text();
825 }
826
830 function getCopyrightIcon() {
832
833 $out = '';
834
835 if ( $wgFooterIcons['copyright']['copyright'] ) {
836 $out = $wgFooterIcons['copyright']['copyright'];
837 } elseif ( $wgRightsIcon ) {
838 $icon = htmlspecialchars( $wgRightsIcon );
839
840 if ( $wgRightsUrl ) {
841 $url = htmlspecialchars( $wgRightsUrl );
842 $out .= '<a href="' . $url . '">';
843 }
844
845 $text = htmlspecialchars( $wgRightsText );
846 $out .= "<img src=\"$icon\" alt=\"$text\" width=\"88\" height=\"31\" />";
847
848 if ( $wgRightsUrl ) {
849 $out .= '</a>';
850 }
851 }
852
853 return $out;
854 }
855
860 function getPoweredBy() {
862
863 $url1 = htmlspecialchars(
864 "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
865 );
866 $url1_5 = htmlspecialchars(
867 "$wgResourceBasePath/resources/assets/poweredby_mediawiki_132x47.png"
868 );
869 $url2 = htmlspecialchars(
870 "$wgResourceBasePath/resources/assets/poweredby_mediawiki_176x62.png"
871 );
872 $text = '<a href="//www.mediawiki.org/"><img src="' . $url1
873 . '" srcset="' . $url1_5 . ' 1.5x, ' . $url2 . ' 2x" '
874 . 'height="31" width="88" alt="Powered by MediaWiki" /></a>';
875 Hooks::run( 'SkinGetPoweredBy', [ &$text, $this ] );
876 return $text;
877 }
878
884 protected function lastModified() {
885 $timestamp = $this->getOutput()->getRevisionTimestamp();
886
887 # No cached timestamp, load it from the database
888 if ( $timestamp === null ) {
889 $timestamp = Revision::getTimestampFromId( $this->getTitle(), $this->getRevisionId() );
890 }
891
892 if ( $timestamp ) {
893 $d = $this->getLanguage()->userDate( $timestamp, $this->getUser() );
894 $t = $this->getLanguage()->userTime( $timestamp, $this->getUser() );
895 $s = ' ' . $this->msg( 'lastmodifiedat', $d, $t )->parse();
896 } else {
897 $s = '';
898 }
899
900 if ( wfGetLB()->getLaggedReplicaMode() ) {
901 $s .= ' <strong>' . $this->msg( 'laggedslavemode' )->parse() . '</strong>';
902 }
903
904 return $s;
905 }
906
911 function logoText( $align = '' ) {
912 if ( $align != '' ) {
913 $a = " style='float: {$align};'";
914 } else {
915 $a = '';
916 }
917
918 $mp = $this->msg( 'mainpage' )->escaped();
919 $mptitle = Title::newMainPage();
920 $url = ( is_object( $mptitle ) ? htmlspecialchars( $mptitle->getLocalURL() ) : '' );
921
922 $logourl = $this->getLogo();
923 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
924
925 return $s;
926 }
927
936 function makeFooterIcon( $icon, $withImage = 'withImage' ) {
937 if ( is_string( $icon ) ) {
938 $html = $icon;
939 } else { // Assuming array
940 $url = isset( $icon["url"] ) ? $icon["url"] : null;
941 unset( $icon["url"] );
942 if ( isset( $icon["src"] ) && $withImage === 'withImage' ) {
943 // do this the lazy way, just pass icon data as an attribute array
944 $html = Html::element( 'img', $icon );
945 } else {
946 $html = htmlspecialchars( $icon["alt"] );
947 }
948 if ( $url ) {
950 $html = Html::rawElement( 'a',
951 [ "href" => $url, "target" => $wgExternalLinkTarget ],
952 $html );
953 }
954 }
955 return $html;
956 }
957
962 function mainPageLink() {
964 Title::newMainPage(),
965 $this->msg( 'mainpage' )->escaped()
966 );
967
968 return $s;
969 }
970
977 public function footerLink( $desc, $page ) {
978 $title = $this->footerLinkTitle( $desc, $page );
979 if ( !$title ) {
980 return '';
981 }
982
983 return Linker::linkKnown(
984 $title,
985 $this->msg( $desc )->escaped()
986 );
987 }
988
994 private function footerLinkTitle( $desc, $page ) {
995 // If the link description has been set to "-" in the default language,
996 if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
997 // then it is disabled, for all languages.
998 return null;
999 }
1000 // Otherwise, we display the link for the user, described in their
1001 // language (which may or may not be the same as the default language),
1002 // but we make the link target be the one site-wide page.
1003 $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
1004
1005 return $title ?: null;
1006 }
1007
1012 function privacyLink() {
1013 return $this->footerLink( 'privacy', 'privacypage' );
1014 }
1015
1020 function aboutLink() {
1021 return $this->footerLink( 'aboutsite', 'aboutpage' );
1022 }
1023
1028 function disclaimerLink() {
1029 return $this->footerLink( 'disclaimers', 'disclaimerpage' );
1030 }
1031
1039 function editUrlOptions() {
1040 $options = [ 'action' => 'edit' ];
1041
1042 if ( !$this->isRevisionCurrent() ) {
1043 $options['oldid'] = intval( $this->getRevisionId() );
1044 }
1045
1046 return $options;
1047 }
1048
1053 function showEmailUser( $id ) {
1054 if ( $id instanceof User ) {
1055 $targetUser = $id;
1056 } else {
1057 $targetUser = User::newFromId( $id );
1058 }
1059
1060 # The sending user must have a confirmed email address and the receiving
1061 # user must accept emails from the sender.
1062 return $this->getUser()->canSendEmail()
1063 && SpecialEmailUser::validateTarget( $targetUser, $this->getUser() ) === '';
1064 }
1065
1077 function getSkinStylePath( $name ) {
1079
1080 if ( $this->stylename === null ) {
1081 $class = static::class;
1082 throw new MWException( "$class::\$stylename must be set to use getSkinStylePath()" );
1083 }
1084
1085 return "$wgStylePath/{$this->stylename}/$name?$wgStyleVersion";
1086 }
1087
1088 /* these are used extensively in SkinTemplate, but also some other places */
1089
1094 static function makeMainPageUrl( $urlaction = '' ) {
1095 $title = Title::newMainPage();
1096 self::checkTitle( $title, '' );
1097
1098 return $title->getLocalURL( $urlaction );
1099 }
1100
1112 static function makeSpecialUrl( $name, $urlaction = '', $proto = null ) {
1114 if ( is_null( $proto ) ) {
1115 return $title->getLocalURL( $urlaction );
1116 } else {
1117 return $title->getFullURL( $urlaction, false, $proto );
1118 }
1119 }
1120
1127 static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) {
1129 return $title->getLocalURL( $urlaction );
1130 }
1131
1137 static function makeI18nUrl( $name, $urlaction = '' ) {
1138 $title = Title::newFromText( wfMessage( $name )->inContentLanguage()->text() );
1140 return $title->getLocalURL( $urlaction );
1141 }
1142
1148 static function makeUrl( $name, $urlaction = '' ) {
1149 $title = Title::newFromText( $name );
1151
1152 return $title->getLocalURL( $urlaction );
1153 }
1154
1161 static function makeInternalOrExternalUrl( $name ) {
1162 if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $name ) ) {
1163 return $name;
1164 } else {
1165 return self::makeUrl( $name );
1166 }
1167 }
1168
1176 static function makeNSUrl( $name, $urlaction = '', $namespace = NS_MAIN ) {
1177 $title = Title::makeTitleSafe( $namespace, $name );
1179
1180 return $title->getLocalURL( $urlaction );
1181 }
1182
1189 static function makeUrlDetails( $name, $urlaction = '' ) {
1190 $title = Title::newFromText( $name );
1192
1193 return [
1194 'href' => $title->getLocalURL( $urlaction ),
1195 'exists' => $title->isKnown(),
1196 ];
1197 }
1198
1205 static function makeKnownUrlDetails( $name, $urlaction = '' ) {
1206 $title = Title::newFromText( $name );
1208
1209 return [
1210 'href' => $title->getLocalURL( $urlaction ),
1211 'exists' => true
1212 ];
1213 }
1214
1221 static function checkTitle( &$title, $name ) {
1222 if ( !is_object( $title ) ) {
1223 $title = Title::newFromText( $name );
1224 if ( !is_object( $title ) ) {
1225 $title = Title::newFromText( '--error: link target missing--' );
1226 }
1227 }
1228 }
1229
1251 function buildSidebar() {
1253
1254 $callback = function () {
1255 $bar = [];
1256 $this->addToSidebar( $bar, 'sidebar' );
1257 Hooks::run( 'SkinBuildSidebar', [ $this, &$bar ] );
1258
1259 return $bar;
1260 };
1261
1262 if ( $wgEnableSidebarCache ) {
1263 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
1264 $sidebar = $cache->getWithSetCallback(
1265 $cache->makeKey( 'sidebar', $this->getLanguage()->getCode() ),
1266 MessageCache::singleton()->isDisabled()
1267 ? $cache::TTL_UNCACHEABLE // bug T133069
1269 $callback,
1270 [ 'lockTSE' => 30 ]
1271 );
1272 } else {
1273 $sidebar = $callback();
1274 }
1275
1276 // Apply post-processing to the cached value
1277 Hooks::run( 'SidebarBeforeOutput', [ $this, &$sidebar ] );
1278
1279 return $sidebar;
1280 }
1281
1291 public function addToSidebar( &$bar, $message ) {
1292 $this->addToSidebarPlain( $bar, wfMessage( $message )->inContentLanguage()->plain() );
1293 }
1294
1302 function addToSidebarPlain( &$bar, $text ) {
1303 $lines = explode( "\n", $text );
1304
1305 $heading = '';
1306 $messageTitle = $this->getConfig()->get( 'EnableSidebarCache' )
1307 ? Title::newMainPage() : $this->getTitle();
1308
1309 foreach ( $lines as $line ) {
1310 if ( strpos( $line, '*' ) !== 0 ) {
1311 continue;
1312 }
1313 $line = rtrim( $line, "\r" ); // for Windows compat
1314
1315 if ( strpos( $line, '**' ) !== 0 ) {
1316 $heading = trim( $line, '* ' );
1317 if ( !array_key_exists( $heading, $bar ) ) {
1318 $bar[$heading] = [];
1319 }
1320 } else {
1321 $line = trim( $line, '* ' );
1322
1323 if ( strpos( $line, '|' ) !== false ) { // sanity check
1324 $line = MessageCache::singleton()->transform( $line, false, null, $messageTitle );
1325 $line = array_map( 'trim', explode( '|', $line, 2 ) );
1326 if ( count( $line ) !== 2 ) {
1327 // Second sanity check, could be hit by people doing
1328 // funky stuff with parserfuncs... (T35321)
1329 continue;
1330 }
1331
1332 $extraAttribs = [];
1333
1334 $msgLink = $this->msg( $line[0] )->title( $messageTitle )->inContentLanguage();
1335 if ( $msgLink->exists() ) {
1336 $link = $msgLink->text();
1337 if ( $link == '-' ) {
1338 continue;
1339 }
1340 } else {
1341 $link = $line[0];
1342 }
1343 $msgText = $this->msg( $line[1] )->title( $messageTitle );
1344 if ( $msgText->exists() ) {
1345 $text = $msgText->text();
1346 } else {
1347 $text = $line[1];
1348 }
1349
1350 if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $link ) ) {
1351 $href = $link;
1352
1353 // Parser::getExternalLinkAttribs won't work here because of the Namespace things
1356 $extraAttribs['rel'] = 'nofollow';
1357 }
1358
1360 if ( $wgExternalLinkTarget ) {
1361 $extraAttribs['target'] = $wgExternalLinkTarget;
1362 }
1363 } else {
1364 $title = Title::newFromText( $link );
1365
1366 if ( $title ) {
1367 $title = $title->fixSpecialName();
1368 $href = $title->getLinkURL();
1369 } else {
1370 $href = 'INVALID-TITLE';
1371 }
1372 }
1373
1374 $bar[$heading][] = array_merge( [
1375 'text' => $text,
1376 'href' => $href,
1377 'id' => Sanitizer::escapeIdForAttribute( 'n-' . strtr( $line[1], ' ', '-' ) ),
1378 'active' => false,
1379 ], $extraAttribs );
1380 } else {
1381 continue;
1382 }
1383 }
1384 }
1385
1386 return $bar;
1387 }
1388
1394 function getNewtalks() {
1395 $newMessagesAlert = '';
1396 $user = $this->getUser();
1397 $newtalks = $user->getNewMessageLinks();
1398 $out = $this->getOutput();
1399
1400 // Allow extensions to disable or modify the new messages alert
1401 if ( !Hooks::run( 'GetNewMessagesAlert', [ &$newMessagesAlert, $newtalks, $user, $out ] ) ) {
1402 return '';
1403 }
1404 if ( $newMessagesAlert ) {
1405 return $newMessagesAlert;
1406 }
1407
1408 if ( count( $newtalks ) == 1 && $newtalks[0]['wiki'] === wfWikiID() ) {
1409 $uTalkTitle = $user->getTalkPage();
1410 $lastSeenRev = isset( $newtalks[0]['rev'] ) ? $newtalks[0]['rev'] : null;
1411 $nofAuthors = 0;
1412 if ( $lastSeenRev !== null ) {
1413 $plural = true; // Default if we have a last seen revision: if unknown, use plural
1414 $latestRev = Revision::newFromTitle( $uTalkTitle, false, Revision::READ_NORMAL );
1415 if ( $latestRev !== null ) {
1416 // Singular if only 1 unseen revision, plural if several unseen revisions.
1417 $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
1418 $nofAuthors = $uTalkTitle->countAuthorsBetween(
1419 $lastSeenRev, $latestRev, 10, 'include_new' );
1420 }
1421 } else {
1422 // Singular if no revision -> diff link will show latest change only in any case
1423 $plural = false;
1424 }
1425 $plural = $plural ? 999 : 1;
1426 // 999 signifies "more than one revision". We don't know how many, and even if we did,
1427 // the number of revisions or authors is not necessarily the same as the number of
1428 // "messages".
1429 $newMessagesLink = Linker::linkKnown(
1430 $uTalkTitle,
1431 $this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
1432 [],
1433 [ 'redirect' => 'no' ]
1434 );
1435
1436 $newMessagesDiffLink = Linker::linkKnown(
1437 $uTalkTitle,
1438 $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->escaped(),
1439 [],
1440 $lastSeenRev !== null
1441 ? [ 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' ]
1442 : [ 'diff' => 'cur' ]
1443 );
1444
1445 if ( $nofAuthors >= 1 && $nofAuthors <= 10 ) {
1446 $newMessagesAlert = $this->msg(
1447 'youhavenewmessagesfromusers',
1448 $newMessagesLink,
1449 $newMessagesDiffLink
1450 )->numParams( $nofAuthors, $plural );
1451 } else {
1452 // $nofAuthors === 11 signifies "11 or more" ("more than 10")
1453 $newMessagesAlert = $this->msg(
1454 $nofAuthors > 10 ? 'youhavenewmessagesmanyusers' : 'youhavenewmessages',
1455 $newMessagesLink,
1456 $newMessagesDiffLink
1457 )->numParams( $plural );
1458 }
1459 $newMessagesAlert = $newMessagesAlert->text();
1460 # Disable CDN cache
1461 $out->setCdnMaxage( 0 );
1462 } elseif ( count( $newtalks ) ) {
1463 $sep = $this->msg( 'newtalkseparator' )->escaped();
1464 $msgs = [];
1465
1466 foreach ( $newtalks as $newtalk ) {
1467 $msgs[] = Xml::element(
1468 'a',
1469 [ 'href' => $newtalk['link'] ], $newtalk['wiki']
1470 );
1471 }
1472 $parts = implode( $sep, $msgs );
1473 $newMessagesAlert = $this->msg( 'youhavenewmessagesmulti' )->rawParams( $parts )->escaped();
1474 $out->setCdnMaxage( 0 );
1475 }
1476
1477 return $newMessagesAlert;
1478 }
1479
1487 private function getCachedNotice( $name ) {
1489
1490 $needParse = false;
1491
1492 if ( $name === 'default' ) {
1493 // special case
1495 $notice = $wgSiteNotice;
1496 if ( empty( $notice ) ) {
1497 return false;
1498 }
1499 } else {
1500 $msg = $this->msg( $name )->inContentLanguage();
1501 if ( $msg->isBlank() ) {
1502 return '';
1503 } elseif ( $msg->isDisabled() ) {
1504 return false;
1505 }
1506 $notice = $msg->plain();
1507 }
1508
1509 $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
1510 $parsed = $cache->getWithSetCallback(
1511 // Use the extra hash appender to let eg SSL variants separately cache
1512 // Key is verified with md5 hash of unparsed wikitext
1513 $cache->makeKey( $name, $wgRenderHashAppend, md5( $notice ) ),
1514 // TTL in seconds
1515 600,
1516 function () use ( $notice ) {
1517 return $this->getOutput()->parse( $notice );
1518 }
1519 );
1520
1521 return Html::rawElement(
1522 'div',
1523 [
1524 'id' => 'localNotice',
1525 'lang' => $wgContLang->getHtmlCode(),
1526 'dir' => $wgContLang->getDir()
1527 ],
1528 $parsed
1529 );
1530 }
1531
1537 function getSiteNotice() {
1538 $siteNotice = '';
1539
1540 if ( Hooks::run( 'SiteNoticeBefore', [ &$siteNotice, $this ] ) ) {
1541 if ( is_object( $this->getUser() ) && $this->getUser()->isLoggedIn() ) {
1542 $siteNotice = $this->getCachedNotice( 'sitenotice' );
1543 } else {
1544 $anonNotice = $this->getCachedNotice( 'anonnotice' );
1545 if ( $anonNotice === false ) {
1546 $siteNotice = $this->getCachedNotice( 'sitenotice' );
1547 } else {
1548 $siteNotice = $anonNotice;
1549 }
1550 }
1551 if ( $siteNotice === false ) {
1552 $siteNotice = $this->getCachedNotice( 'default' );
1553 }
1554 }
1555
1556 Hooks::run( 'SiteNoticeAfter', [ &$siteNotice, $this ] );
1557 return $siteNotice;
1558 }
1559
1573 public function doEditSectionLink( Title $nt, $section, $tooltip = null, $lang = false ) {
1574 // HTML generated here should probably have userlangattributes
1575 // added to it for LTR text on RTL pages
1576
1578
1579 $attribs = [];
1580 if ( !is_null( $tooltip ) ) {
1581 $attribs['title'] = wfMessage( 'editsectionhint' )->rawParams( $tooltip )
1582 ->inLanguage( $lang )->text();
1583 }
1584
1585 $links = [
1586 'editsection' => [
1587 'text' => wfMessage( 'editsection' )->inLanguage( $lang )->escaped(),
1588 'targetTitle' => $nt,
1589 'attribs' => $attribs,
1590 'query' => [ 'action' => 'edit', 'section' => $section ],
1591 'options' => [ 'noclasses', 'known' ]
1592 ]
1593 ];
1594
1595 Hooks::run( 'SkinEditSectionLinks', [ $this, $nt, $section, $tooltip, &$links, $lang ] );
1596
1597 $result = '<span class="mw-editsection"><span class="mw-editsection-bracket">[</span>';
1598
1599 $linksHtml = [];
1600 foreach ( $links as $k => $linkDetails ) {
1601 $linksHtml[] = Linker::link(
1602 $linkDetails['targetTitle'],
1603 $linkDetails['text'],
1604 $linkDetails['attribs'],
1605 $linkDetails['query'],
1606 $linkDetails['options']
1607 );
1608 }
1609
1610 $result .= implode(
1611 '<span class="mw-editsection-divider">'
1612 . wfMessage( 'pipe-separator' )->inLanguage( $lang )->escaped()
1613 . '</span>',
1614 $linksHtml
1615 );
1616
1617 $result .= '<span class="mw-editsection-bracket">]</span></span>';
1618 // Deprecated, use SkinEditSectionLinks hook instead
1619 Hooks::run(
1620 'DoEditSectionLink',
1621 [ $this, $nt, $section, $tooltip, &$result, $lang ],
1622 '1.25'
1623 );
1624 return $result;
1625 }
1626
1627}
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
$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...
$wgStyleVersion
Bump this number when changing the global style sheets and JavaScript.
$wgUseAjax
Enable AJAX framework.
$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.
$wgEnableWriteAPI
Allow the API to be used to perform write operations (page edits, rollback, etc.) when an authorised ...
$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.
$wgSquidMaxage
Cache TTL for the CDN sent as s-maxage (without ESI) or Surrogate-Control (with ESI).
$wgUseCategoryBrowser
Use experimental, DMOZ-like category browser.
$wgExternalLinkTarget
Set a default target for external links, e.g.
$wgEnableAPI
Enable the MediaWiki API for convenient access to machine-readable data via api.php.
$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.
wfGetLB( $wiki=false)
Get a load balancer object.
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:58
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()
getUser()
Get the User object.
getRequest()
Get the WebRequest object.
getConfig()
Get the Config object.
getTitle()
Get the Title object.
getOutput()
Get the OutputPage object.
getLanguage()
Get the Language object.
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:107
static linkKnown( $target, $html=null, $customAttribs=[], $query=[], $options=[ 'known'])
Identical to link(), except $options defaults to 'known'.
Definition Linker.php:164
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
Definition Linker.php:843
MediaWiki exception.
MediaWikiServices is the service locator for the application scope of MediaWiki.
static singleton()
Get the signleton instance of this class.
This class should be covered by a general architecture document which does not exist as of January 20...
static makeConfigSetScript(array $configuration)
Returns JS code which will set the MediaWiki configuration array to the given value.
static makeInlineScript( $script)
Construct an inline script tag with given JS code.
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:134
The main skin class which provides methods and properties for all other skins.
Definition Skin.php:36
aboutLink()
Gets the link to the wiki's about page.
Definition Skin.php:1020
isRevisionCurrent()
Whether the revision displayed is the latest revision of the page.
Definition Skin.php:285
static makeInternalOrExternalUrl( $name)
If url string starts with http, consider as external URL, else internal.
Definition Skin.php:1161
afterContentHook()
This runs a hook to allow extensions placing their stuff after content and article metadata (e....
Definition Skin.php:605
string $stylename
Stylesheets set to use.
Definition Skin.php:45
getNewtalks()
Gets new talk page messages for the current user and returns an appropriate alert message (or an empt...
Definition Skin.php:1394
mainPageLink()
Gets the link to the wiki's main page.
Definition Skin.php:962
static getAllowedSkins()
Fetch the list of user-selectable skins in regards to $wgSkipSkins.
Definition Skin.php:74
getSkinStylePath( $name)
Return a fully resolved style path url to images or styles stored in the current skins's folder.
Definition Skin.php:1077
getCachedNotice( $name)
Get a cached notice.
Definition Skin.php:1487
static makeMainPageUrl( $urlaction='')
Definition Skin.php:1094
static makeKnownUrlDetails( $name, $urlaction='')
Make URL details where the article exists (or at least it's convenient to think so)
Definition Skin.php:1205
generateDebugHTML()
Generate debug data HTML for displaying at the bottom of the main content area.
Definition Skin.php:631
getCopyrightIcon()
Definition Skin.php:830
privacyLink()
Gets the link to the wiki's privacy policy page.
Definition Skin.php:1012
footerLinkTitle( $desc, $page)
Definition Skin.php:994
getSiteNotice()
Get the site notice.
Definition Skin.php:1537
getHtmlElementAttributes()
Return values for <html> element.
Definition Skin.php:438
static getSkinNames()
Fetch the set of available skins.
Definition Skin.php:51
static normalizeKey( $key)
Normalize a skin preference value to a form that can be loaded.
Definition Skin.php:95
getSkinName()
Definition Skin.php:139
getUndeleteLink()
Definition Skin.php:674
getPoweredBy()
Gets the powered by MediaWiki icon.
Definition Skin.php:860
getCategoryLinks()
Definition Skin.php:479
escapeSearchLink()
Definition Skin.php:776
static makeUrlDetails( $name, $urlaction='')
these return an array with the 'href' and boolean 'exists'
Definition Skin.php:1189
getLogo()
URL to the logo.
Definition Skin.php:462
$mRelevantTitle
Definition Skin.php:38
addToSidebar(&$bar, $message)
Add content from a sidebar system message Currently only used for MediaWiki:Sidebar (but may be used ...
Definition Skin.php:1291
static makeSpecialUrlSubpage( $name, $subpage, $urlaction='')
Definition Skin.php:1127
getRelevantUser()
Return the "relevant" user.
Definition Skin.php:333
setRelevantTitle( $t)
Set the "relevant" title.
Definition Skin.php:295
logoText( $align='')
Definition Skin.php:911
addToBodyAttributes( $out, &$bodyAttrs)
This will be called by OutputPage::headElement when it is creating the "<body>" tag,...
Definition Skin.php:454
$mRelevantUser
Definition Skin.php:39
drawCategoryBrowser( $tree)
Render the array as a series of links.
Definition Skin.php:547
$skinname
Definition Skin.php:37
static checkTitle(&$title, $name)
make sure we have some title to operate on
Definition Skin.php:1221
static makeUrl( $name, $urlaction='')
Definition Skin.php:1148
showIPinHeader()
Definition Skin.php:760
getPageClasses( $title)
TODO: document.
Definition Skin.php:410
getSearchLink()
Definition Skin.php:768
editUrlOptions()
Return URL options for the 'edit page' link.
Definition Skin.php:1039
static makeVariablesScript( $data)
Definition Skin.php:368
showEmailUser( $id)
Definition Skin.php:1053
static makeNSUrl( $name, $urlaction='', $namespace=NS_MAIN)
this can be passed the NS number as defined in Language.php
Definition Skin.php:1176
buildSidebar()
Build an array that represents the sidebar(s), the navigation bar among them.
Definition Skin.php:1251
getCopyright( $type='detect')
Definition Skin.php:784
printSource()
Text with the permalink to the source page, usually shown on the footer of a printed page.
Definition Skin.php:656
shouldPreloadLogo()
Whether the logo should be preloaded with an HTTP link header or not.
Definition Skin.php:472
setRelevantUser( $u)
Set the "relevant" user.
Definition Skin.php:321
setupSkinUserCss(OutputPage $out)
Add skin specific stylesheets Calling this method with an $out of anything but the same OutputPage in...
static getSkinNameMessages()
Fetch the skinname messages for available skins.
Definition Skin.php:59
makeFooterIcon( $icon, $withImage='withImage')
Renders a $wgFooterIcons icon according to the method's arguments.
Definition Skin.php:936
getRevisionId()
Get the current revision ID.
Definition Skin.php:276
preloadExistence()
Preload the existence of three commonly-requested pages in a single query.
Definition Skin.php:231
bottomScripts()
This gets called shortly before the "</body>" tag.
Definition Skin.php:640
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:1573
disclaimerLink()
Gets the link to the wiki's general disclaimers page.
Definition Skin.php:1028
getDefaultModules()
Defines the ResourceLoader modules that should be added to the skin It is recommended that skins wish...
Definition Skin.php:159
static makeSpecialUrl( $name, $urlaction='', $proto=null)
Make a URL for a Special Page using the given query and protocol.
Definition Skin.php:1112
lastModified()
Get the timestamp of the latest revision, formatted in user language.
Definition Skin.php:884
initPage(OutputPage $out)
Definition Skin.php:146
static getDynamicStylesheetQuery()
Get the query to generate a dynamic stylesheet.
Definition Skin.php:383
subPageSubtitle( $out=null)
Definition Skin.php:703
addToSidebarPlain(&$bar, $text)
Add content from plain text.
Definition Skin.php:1302
footerLink( $desc, $page)
Returns an HTML link for use in the footer.
Definition Skin.php:977
static makeI18nUrl( $name, $urlaction='')
Definition Skin.php:1137
getRelevantTitle()
Return the "relevant" title.
Definition Skin.php:309
getCategories()
Definition Skin.php:570
static validateTarget( $target, User $sender=null)
Validate target User.
static resolveAlias( $alias)
Given a special page name with a possible subpage, return an array where the first element is the spe...
static getSafeTitleFor( $name, $subpage=false)
Get a localised Title object for a page name with a possibly unvalidated subpage.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
Represents a title within MediaWiki.
Definition Title.php:39
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:51
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 class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the local content language as $wgContLang
Definition design.txt:57
when a variable name is used in a it is silently declared as a new local masking the global
Definition design.txt:95
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition design.txt:18
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:67
const NS_MAIN
Definition Defines.php:65
const NS_CATEGORY
Definition Defines.php:79
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. '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 '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! 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! 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:1963
either a plain
Definition hooks.txt:2026
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:1971
namespace and then decline to actually register it file or subcat img or subcat $title
Definition hooks.txt:962
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 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
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:1976
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:862
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:1983
usually copyright or history_copyright This message must be in HTML not wikitext & $link
Definition hooks.txt:2989
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:302
if the prop value should be in the metadata multi language array can modify can modify indexed by page_id indexed by prefixed DB keys can modify can modify can modify this should be populated with an alert message to that effect $newtalks
Definition hooks.txt:1712
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:1984
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:2990
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
$lines
Definition router.php:61
if(!isset( $args[0])) $lang