MediaWiki  master
Skin.php
Go to the documentation of this file.
1 <?php
26 
38 abstract class Skin extends ContextSource {
42  protected $skinname = null;
43 
44  protected $mRelevantTitle = null;
45  protected $mRelevantUser = null;
46 
51  public $stylename = null;
52 
57  static function getSkinNames() {
58  $skinFactory = MediaWikiServices::getInstance()->getSkinFactory();
59  return $skinFactory->getSkinNames();
60  }
61 
67  static function getSkinNameMessages() {
68  wfDeprecated( __METHOD__, '1.34' );
69  $messages = [];
70  foreach ( self::getSkinNames() as $skinKey => $skinName ) {
71  $messages[] = "skinname-$skinKey";
72  }
73  return $messages;
74  }
75 
83  public static function getAllowedSkins() {
84  global $wgSkipSkins;
85 
86  $allowedSkins = self::getSkinNames();
87 
88  foreach ( $wgSkipSkins as $skip ) {
89  unset( $allowedSkins[$skip] );
90  }
91 
92  return $allowedSkins;
93  }
94 
104  static function normalizeKey( $key ) {
106 
107  $skinNames = self::getSkinNames();
108 
109  // Make keys lowercase for case-insensitive matching.
110  $skinNames = array_change_key_case( $skinNames, CASE_LOWER );
111  $key = strtolower( $key );
112  $defaultSkin = strtolower( $wgDefaultSkin );
113  $fallbackSkin = strtolower( $wgFallbackSkin );
114 
115  if ( $key == '' || $key == 'default' ) {
116  // Don't return the default immediately;
117  // in a misconfiguration we need to fall back.
118  $key = $defaultSkin;
119  }
120 
121  if ( isset( $skinNames[$key] ) ) {
122  return $key;
123  }
124 
125  // Older versions of the software used a numeric setting
126  // in the user preferences.
127  $fallback = [
128  0 => $defaultSkin,
129  2 => 'cologneblue'
130  ];
131 
132  if ( isset( $fallback[$key] ) ) {
133  $key = $fallback[$key];
134  }
135 
136  if ( isset( $skinNames[$key] ) ) {
137  return $key;
138  } elseif ( isset( $skinNames[$defaultSkin] ) ) {
139  return $defaultSkin;
140  } else {
141  return $fallbackSkin;
142  }
143  }
144 
149  public function __construct( $skinname = null ) {
150  if ( is_string( $skinname ) ) {
151  $this->skinname = $skinname;
152  }
153  }
154 
158  public function getSkinName() {
159  return $this->skinname;
160  }
161 
165  public function initPage( OutputPage $out ) {
166  $this->preloadExistence();
167  }
168 
179  public function getDefaultModules() {
180  $out = $this->getOutput();
181  $user = $this->getUser();
182 
183  // Modules declared in the $modules literal are loaded
184  // for ALL users, on ALL pages, in ALL skins.
185  // Keep this list as small as possible!
186  $modules = [
187  'styles' => [
188  // The 'styles' key sets render-blocking style modules
189  // Unlike other keys in $modules, this is an associative array
190  // where each key is its own group pointing to a list of modules
191  'core' => [
192  'mediawiki.legacy.shared',
193  'mediawiki.legacy.commonPrint',
194  ],
195  'content' => [],
196  'syndicate' => [],
197  ],
198  'core' => [
199  'site',
200  'mediawiki.page.startup',
201  ],
202  // modules that enhance the content in some way
203  'content' => [
204  'mediawiki.page.ready',
205  ],
206  // modules relating to search functionality
207  'search' => [
208  'mediawiki.searchSuggest',
209  ],
210  // modules relating to functionality relating to watching an article
211  'watch' => [],
212  // modules which relate to the current users preferences
213  'user' => [],
214  // modules relating to RSS/Atom Feeds
215  'syndicate' => [],
216  ];
217 
218  // Preload jquery.tablesorter for mediawiki.page.ready
219  if ( strpos( $out->getHTML(), 'sortable' ) !== false ) {
220  $modules['content'][] = 'jquery.tablesorter';
221  $modules['styles']['content'][] = 'jquery.tablesorter.styles';
222  }
223 
224  // Preload jquery.makeCollapsible for mediawiki.page.ready
225  if ( strpos( $out->getHTML(), 'mw-collapsible' ) !== false ) {
226  $modules['content'][] = 'jquery.makeCollapsible';
227  $modules['styles']['content'][] = 'jquery.makeCollapsible.styles';
228  }
229 
230  // Deprecated since 1.26: Unconditional loading of mediawiki.ui.button
231  // on every page is deprecated. Express a dependency instead.
232  if ( strpos( $out->getHTML(), 'mw-ui-button' ) !== false ) {
233  $modules['styles']['content'][] = 'mediawiki.ui.button';
234  }
235 
236  if ( $out->isTOCEnabled() ) {
237  $modules['content'][] = 'mediawiki.toc';
238  $modules['styles']['content'][] = 'mediawiki.toc.styles';
239  }
240 
241  $prefMgr = MediaWikiServices::getInstance()->getPermissionManager();
242  if ( $user->isLoggedIn()
243  && $prefMgr->userHasAllRights( $user, 'writeapi', 'viewmywatchlist', 'editmywatchlist' )
244  && $this->getRelevantTitle()->canExist()
245  ) {
246  $modules['watch'][] = 'mediawiki.page.watch.ajax';
247  }
248 
249  if ( $user->getBoolOption( 'editsectiononrightclick' )
250  || ( $out->isArticle() && $user->getOption( 'editondblclick' ) )
251  ) {
252  $modules['user'][] = 'mediawiki.misc-authed-pref';
253  }
254 
255  if ( $out->isSyndicated() ) {
256  $modules['styles']['syndicate'][] = 'mediawiki.feedlink';
257  }
258 
259  return $modules;
260  }
261 
265  protected function preloadExistence() {
266  $titles = [];
267 
268  // User/talk link
269  $user = $this->getUser();
270  if ( $user->isLoggedIn() ) {
271  $titles[] = $user->getUserPage();
272  $titles[] = $user->getTalkPage();
273  }
274 
275  // Check, if the page can hold some kind of content, otherwise do nothing
276  $title = $this->getRelevantTitle();
277  if ( $title->canExist() && $title->canHaveTalkPage() ) {
278  $namespaceInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
279 
280  if ( $title->isTalkPage() ) {
281  $titles[] = $namespaceInfo->getSubjectPage( $title );
282  } else {
283  $titles[] = $namespaceInfo->getTalkPage( $title );
284  }
285  }
286 
287  // Footer links (used by SkinTemplate::prepareQuickTemplate)
288  foreach ( [
289  $this->footerLinkTitle( 'privacy', 'privacypage' ),
290  $this->footerLinkTitle( 'aboutsite', 'aboutpage' ),
291  $this->footerLinkTitle( 'disclaimers', 'disclaimerpage' ),
292  ] as $title ) {
293  if ( $title ) {
294  $titles[] = $title;
295  }
296  }
297 
298  Hooks::run( 'SkinPreloadExistence', [ &$titles, $this ] );
299 
300  if ( $titles ) {
301  $lb = new LinkBatch( $titles );
302  $lb->setCaller( __METHOD__ );
303  $lb->execute();
304  }
305  }
306 
313  public function getRevisionId() {
314  return $this->getOutput()->getRevisionId();
315  }
316 
323  public function isRevisionCurrent() {
324  return $this->getOutput()->isRevisionCurrent();
325  }
326 
332  public function setRelevantTitle( $t ) {
333  $this->mRelevantTitle = $t;
334  }
335 
346  public function getRelevantTitle() {
347  return $this->mRelevantTitle ?? $this->getTitle();
348  }
349 
355  public function setRelevantUser( $u ) {
356  $this->mRelevantUser = $u;
357  }
358 
367  public function getRelevantUser() {
368  if ( isset( $this->mRelevantUser ) ) {
369  return $this->mRelevantUser;
370  }
371  $title = $this->getRelevantTitle();
372  if ( $title->hasSubjectNamespace( NS_USER ) ) {
373  $rootUser = $title->getRootText();
374  if ( User::isIP( $rootUser ) ) {
375  $this->mRelevantUser = User::newFromName( $rootUser, false );
376  } else {
377  $user = User::newFromName( $rootUser, false );
378 
379  if ( $user ) {
380  $user->load( User::READ_NORMAL );
381 
382  if ( $user->isLoggedIn() ) {
383  $this->mRelevantUser = $user;
384  }
385  }
386  }
387  return $this->mRelevantUser;
388  }
389  return null;
390  }
391 
395  abstract function outputPage();
396 
402  public static function makeVariablesScript( $data, $nonce = null ) {
403  if ( $data ) {
406  $nonce
407  );
408  }
409  return '';
410  }
411 
418  public static function getDynamicStylesheetQuery() {
419  wfDeprecated( __METHOD__, '1.35' );
420  return [
421  'action' => 'raw',
422  'ctype' => 'text/css',
423  ];
424  }
425 
432  public function setupSkinUserCss( OutputPage $out ) {
433  // Stub.
434  }
435 
441  function getPageClasses( $title ) {
442  $numeric = 'ns-' . $title->getNamespace();
443  $user = $this->getUser();
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  } else {
456  if ( $title->isTalkPage() ) {
457  $type = 'ns-talk';
458  } else {
459  $type = 'ns-subject';
460  }
461  // T208315: add HTML class when the user can edit the page
462  if ( MediaWikiServices::getInstance()->getPermissionManager()
463  ->quickUserCan( 'edit', $user, $title )
464  ) {
465  $type .= ' mw-editable';
466  }
467  }
468 
469  $name = Sanitizer::escapeClass( 'page-' . $title->getPrefixedText() );
470  $root = Sanitizer::escapeClass( 'rootpage-' . $title->getRootTitle()->getPrefixedText() );
471 
472  return "$numeric $type $name $root";
473  }
474 
479  public function getHtmlElementAttributes() {
480  $lang = $this->getLanguage();
481  return [
482  'lang' => $lang->getHtmlCode(),
483  'dir' => $lang->getDir(),
484  'class' => 'client-nojs',
485  ];
486  }
487 
495  function addToBodyAttributes( $out, &$bodyAttrs ) {
496  // does nothing by default
497  }
498 
503  function getLogo() {
504  return $this->getConfig()->get( 'Logo' );
505  }
506 
516  public function shouldPreloadLogo() {
517  return false;
518  }
519 
523  function getCategoryLinks() {
524  $out = $this->getOutput();
525  $allCats = $out->getCategoryLinks();
526  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
527 
528  if ( $allCats === [] ) {
529  return '';
530  }
531 
532  $embed = "<li>";
533  $pop = "</li>";
534 
535  $s = '';
536  $colon = $this->msg( 'colon-separator' )->escaped();
537 
538  if ( !empty( $allCats['normal'] ) ) {
539  $t = $embed . implode( $pop . $embed, $allCats['normal'] ) . $pop;
540 
541  $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) );
542  $linkPage = $this->msg( 'pagecategorieslink' )->inContentLanguage()->text();
543  $title = Title::newFromText( $linkPage );
544  $link = $title ? $linkRenderer->makeLink( $title, $msg->text() ) : $msg->escaped();
545  $s .= '<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
546  $link . $colon . '<ul>' . $t . '</ul></div>';
547  }
548 
549  # Hidden categories
550  if ( isset( $allCats['hidden'] ) ) {
551  if ( $this->getUser()->getBoolOption( 'showhiddencats' ) ) {
552  $class = ' mw-hidden-cats-user-shown';
553  } elseif ( $this->getTitle()->getNamespace() == NS_CATEGORY ) {
554  $class = ' mw-hidden-cats-ns-shown';
555  } else {
556  $class = ' mw-hidden-cats-hidden';
557  }
558 
559  $s .= "<div id=\"mw-hidden-catlinks\" class=\"mw-hidden-catlinks$class\">" .
560  $this->msg( 'hidden-categories' )->numParams( count( $allCats['hidden'] ) )->escaped() .
561  $colon . '<ul>' . $embed . implode( $pop . $embed, $allCats['hidden'] ) . $pop . '</ul>' .
562  '</div>';
563  }
564 
565  # optional 'dmoz-like' category browser. Will be shown under the list
566  # of categories an article belong to
567  if ( $this->getConfig()->get( 'UseCategoryBrowser' ) ) {
568  $s .= '<br /><hr />';
569 
570  # get a big array of the parents tree
571  $parenttree = $this->getTitle()->getParentCategoryTree();
572  # Skin object passed by reference cause it can not be
573  # accessed under the method subfunction drawCategoryBrowser
574  $tempout = explode( "\n", $this->drawCategoryBrowser( $parenttree ) );
575  # Clean out bogus first entry and sort them
576  unset( $tempout[0] );
577  asort( $tempout );
578  # Output one per line
579  $s .= implode( "<br />\n", $tempout );
580  }
581 
582  return $s;
583  }
584 
590  function drawCategoryBrowser( $tree ) {
591  $return = '';
592  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
593 
594  foreach ( $tree as $element => $parent ) {
595  if ( empty( $parent ) ) {
596  # element start a new list
597  $return .= "\n";
598  } else {
599  # grab the others elements
600  $return .= $this->drawCategoryBrowser( $parent ) . ' &gt; ';
601  }
602 
603  # add our current element to the list
604  $eltitle = Title::newFromText( $element );
605  $return .= $linkRenderer->makeLink( $eltitle, $eltitle->getText() );
606  }
607 
608  return $return;
609  }
610 
614  function getCategories() {
615  $out = $this->getOutput();
616  $catlinks = $this->getCategoryLinks();
617 
618  // Check what we're showing
619  $allCats = $out->getCategoryLinks();
620  $showHidden = $this->getUser()->getBoolOption( 'showhiddencats' ) ||
621  $this->getTitle()->getNamespace() == NS_CATEGORY;
622 
623  $classes = [ 'catlinks' ];
624  if ( empty( $allCats['normal'] ) && !( !empty( $allCats['hidden'] ) && $showHidden ) ) {
625  $classes[] = 'catlinks-allhidden';
626  }
627 
628  return Html::rawElement(
629  'div',
630  [ 'id' => 'catlinks', 'class' => $classes, 'data-mw' => 'interface' ],
631  $catlinks
632  );
633  }
634 
649  protected function afterContentHook() {
650  $data = '';
651 
652  if ( Hooks::run( 'SkinAfterContent', [ &$data, $this ] ) ) {
653  // adding just some spaces shouldn't toggle the output
654  // of the whole <div/>, so we use trim() here
655  if ( trim( $data ) != '' ) {
656  // Doing this here instead of in the skins to
657  // ensure that the div has the same ID in all
658  // skins
659  $data = "<div id='mw-data-after-content'>\n" .
660  "\t$data\n" .
661  "</div>\n";
662  }
663  } else {
664  wfDebug( "Hook SkinAfterContent changed output processing.\n" );
665  }
666 
667  return $data;
668  }
669 
675  protected function generateDebugHTML() {
676  return MWDebug::getHTMLDebugLog();
677  }
678 
684  function bottomScripts() {
685  // TODO and the suckage continues. This function is really just a wrapper around
686  // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
687  // up at some point
688  $chunks = [ $this->getOutput()->getBottomScripts() ];
689 
690  // Keep the hook appendage separate to preserve WrappedString objects.
691  // This enables BaseTemplate::getTrail() to merge them where possible.
692  $extraHtml = '';
693  Hooks::run( 'SkinAfterBottomScripts', [ $this, &$extraHtml ] );
694  if ( $extraHtml !== '' ) {
695  $chunks[] = $extraHtml;
696  }
697  return WrappedString::join( "\n", $chunks );
698  }
699 
706  function printSource() {
707  $oldid = $this->getOutput()->getRevisionId();
708  if ( $oldid ) {
709  $canonicalUrl = $this->getTitle()->getCanonicalURL( 'oldid=' . $oldid );
710  $url = htmlspecialchars( wfExpandIRI( $canonicalUrl ) );
711  } else {
712  // oldid not available for non existing pages
713  $url = htmlspecialchars( wfExpandIRI( $this->getTitle()->getCanonicalURL() ) );
714  }
715 
716  return $this->msg( 'retrievedfrom' )
717  ->rawParams( '<a dir="ltr" href="' . $url . '">' . $url . '</a>' )
718  ->parse();
719  }
720 
724  function getUndeleteLink() {
725  $action = $this->getRequest()->getVal( 'action', 'view' );
726  $title = $this->getTitle();
727  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
728  $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
729 
730  if ( ( !$title->exists() || $action == 'history' ) &&
731  $permissionManager->quickUserCan( 'deletedhistory', $this->getUser(), $title )
732  ) {
733  $n = $title->isDeleted();
734 
735  if ( $n ) {
736  if ( $permissionManager->quickUserCan( 'undelete',
737  $this->getUser(), $this->getTitle() )
738  ) {
739  $msg = 'thisisdeleted';
740  } else {
741  $msg = 'viewdeleted';
742  }
743 
744  $subtitle = $this->msg( $msg )->rawParams(
745  $linkRenderer->makeKnownLink(
746  SpecialPage::getTitleFor( 'Undelete', $this->getTitle()->getPrefixedDBkey() ),
747  $this->msg( 'restorelink' )->numParams( $n )->text() )
748  )->escaped();
749 
750  // Allow extensions to add more links
751  $links = [];
752  Hooks::run( 'UndeletePageToolLinks', [ $this->getContext(), $linkRenderer, &$links ] );
753 
754  if ( $links ) {
755  $subtitle .= ''
756  . $this->msg( 'word-separator' )->escaped()
757  . $this->msg( 'parentheses' )
758  ->rawParams( $this->getLanguage()->pipeList( $links ) )
759  ->escaped();
760  }
761  return Html::rawElement( 'div', [ 'class' => 'mw-undelete-subtitle' ], $subtitle );
762  }
763  }
764 
765  return '';
766  }
767 
772  function subPageSubtitle( $out = null ) {
773  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
774  if ( $out === null ) {
775  $out = $this->getOutput();
776  }
777  $title = $out->getTitle();
778  $subpages = '';
779 
780  if ( !Hooks::run( 'SkinSubPageSubtitle', [ &$subpages, $this, $out ] ) ) {
781  return $subpages;
782  }
783 
784  if (
785  $out->isArticle() && MediaWikiServices::getInstance()->getNamespaceInfo()->
786  hasSubpages( $title->getNamespace() )
787  ) {
788  $ptext = $title->getPrefixedText();
789  if ( strpos( $ptext, '/' ) !== false ) {
790  $links = explode( '/', $ptext );
791  array_pop( $links );
792  $c = 0;
793  $growinglink = '';
794  $display = '';
795  $lang = $this->getLanguage();
796 
797  foreach ( $links as $link ) {
798  $growinglink .= $link;
799  $display .= $link;
800  $linkObj = Title::newFromText( $growinglink );
801 
802  if ( is_object( $linkObj ) && $linkObj->isKnown() ) {
803  $getlink = $linkRenderer->makeKnownLink(
804  $linkObj, $display
805  );
806 
807  $c++;
808 
809  if ( $c > 1 ) {
810  $subpages .= $lang->getDirMarkEntity() . $this->msg( 'pipe-separator' )->escaped();
811  } else {
812  $subpages .= '&lt; ';
813  }
814 
815  $subpages .= $getlink;
816  $display = '';
817  } else {
818  $display .= '/';
819  }
820  $growinglink .= '/';
821  }
822  }
823  }
824 
825  return $subpages;
826  }
827 
831  function getSearchLink() {
833  return $searchPage->getLocalURL();
834  }
835 
840  function escapeSearchLink() {
841  wfDeprecated( __METHOD__, '1.34' );
842  return htmlspecialchars( $this->getSearchLink() );
843  }
844 
849  function getCopyright( $type = 'detect' ) {
850  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
851  if ( $type == 'detect' ) {
852  if ( !$this->getOutput()->isRevisionCurrent()
853  && !$this->msg( 'history_copyright' )->inContentLanguage()->isDisabled()
854  ) {
855  $type = 'history';
856  } else {
857  $type = 'normal';
858  }
859  }
860 
861  if ( $type == 'history' ) {
862  $msg = 'history_copyright';
863  } else {
864  $msg = 'copyright';
865  }
866 
867  $config = $this->getConfig();
868 
869  if ( $config->get( 'RightsPage' ) ) {
870  $title = Title::newFromText( $config->get( 'RightsPage' ) );
871  $link = $linkRenderer->makeKnownLink(
872  $title, new HtmlArmor( $config->get( 'RightsText' ) )
873  );
874  } elseif ( $config->get( 'RightsUrl' ) ) {
875  $link = Linker::makeExternalLink( $config->get( 'RightsUrl' ), $config->get( 'RightsText' ) );
876  } elseif ( $config->get( 'RightsText' ) ) {
877  $link = $config->get( 'RightsText' );
878  } else {
879  # Give up now
880  return '';
881  }
882 
883  // Allow for site and per-namespace customization of copyright notice.
884  Hooks::run( 'SkinCopyrightFooter', [ $this->getTitle(), $type, &$msg, &$link ] );
885 
886  return $this->msg( $msg )->rawParams( $link )->text();
887  }
888 
892  function getCopyrightIcon() {
893  $out = '';
894  $config = $this->getConfig();
895 
896  $footerIcons = $config->get( 'FooterIcons' );
897  if ( $footerIcons['copyright']['copyright'] ) {
898  $out = $footerIcons['copyright']['copyright'];
899  } elseif ( $config->get( 'RightsIcon' ) ) {
900  $icon = htmlspecialchars( $config->get( 'RightsIcon' ) );
901  $url = $config->get( 'RightsUrl' );
902 
903  if ( $url ) {
904  $out .= '<a href="' . htmlspecialchars( $url ) . '">';
905  }
906 
907  $text = htmlspecialchars( $config->get( 'RightsText' ) );
908  $out .= "<img src=\"$icon\" alt=\"$text\" width=\"88\" height=\"31\" />";
909 
910  if ( $url ) {
911  $out .= '</a>';
912  }
913  }
914 
915  return $out;
916  }
917 
922  function getPoweredBy() {
923  $resourceBasePath = $this->getConfig()->get( 'ResourceBasePath' );
924  $url1 = htmlspecialchars(
925  "$resourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
926  );
927  $url1_5 = htmlspecialchars(
928  "$resourceBasePath/resources/assets/poweredby_mediawiki_132x47.png"
929  );
930  $url2 = htmlspecialchars(
931  "$resourceBasePath/resources/assets/poweredby_mediawiki_176x62.png"
932  );
933  $text = '<a href="https://www.mediawiki.org/"><img src="' . $url1
934  . '" srcset="' . $url1_5 . ' 1.5x, ' . $url2 . ' 2x" '
935  . 'height="31" width="88" alt="Powered by MediaWiki" /></a>';
936  Hooks::run( 'SkinGetPoweredBy', [ &$text, $this ] );
937  return $text;
938  }
939 
945  protected function lastModified() {
946  $timestamp = $this->getOutput()->getRevisionTimestamp();
947 
948  # No cached timestamp, load it from the database
949  if ( $timestamp === null ) {
950  $timestamp = Revision::getTimestampFromId( $this->getTitle(),
951  $this->getOutput()->getRevisionId() );
952  }
953 
954  if ( $timestamp ) {
955  $d = $this->getLanguage()->userDate( $timestamp, $this->getUser() );
956  $t = $this->getLanguage()->userTime( $timestamp, $this->getUser() );
957  $s = ' ' . $this->msg( 'lastmodifiedat', $d, $t )->parse();
958  } else {
959  $s = '';
960  }
961 
962  if ( MediaWikiServices::getInstance()->getDBLoadBalancer()->getLaggedReplicaMode() ) {
963  $s .= ' <strong>' . $this->msg( 'laggedslavemode' )->parse() . '</strong>';
964  }
965 
966  return $s;
967  }
968 
973  function logoText( $align = '' ) {
974  if ( $align != '' ) {
975  $a = " style='float: {$align};'";
976  } else {
977  $a = '';
978  }
979 
980  $mp = $this->msg( 'mainpage' )->escaped();
981  $mptitle = Title::newMainPage();
982  $url = ( is_object( $mptitle ) ? htmlspecialchars( $mptitle->getLocalURL() ) : '' );
983 
984  $logourl = $this->getLogo();
985  $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
986 
987  return $s;
988  }
989 
998  function makeFooterIcon( $icon, $withImage = 'withImage' ) {
999  if ( is_string( $icon ) ) {
1000  $html = $icon;
1001  } else { // Assuming array
1002  $url = $icon["url"] ?? null;
1003  unset( $icon["url"] );
1004  if ( isset( $icon["src"] ) && $withImage === 'withImage' ) {
1005  // do this the lazy way, just pass icon data as an attribute array
1006  $html = Html::element( 'img', $icon );
1007  } else {
1008  $html = htmlspecialchars( $icon["alt"] );
1009  }
1010  if ( $url ) {
1011  $html = Html::rawElement( 'a',
1012  [ "href" => $url, "target" => $this->getConfig()->get( 'ExternalLinkTarget' ) ],
1013  $html );
1014  }
1015  }
1016  return $html;
1017  }
1018 
1023  function mainPageLink() {
1024  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1025  $s = $linkRenderer->makeKnownLink(
1027  $this->msg( 'mainpage' )->text()
1028  );
1029 
1030  return $s;
1031  }
1032 
1039  public function footerLink( $desc, $page ) {
1040  $title = $this->footerLinkTitle( $desc, $page );
1041  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1042  if ( !$title ) {
1043  return '';
1044  }
1045 
1046  return $linkRenderer->makeKnownLink(
1047  $title,
1048  $this->msg( $desc )->text()
1049  );
1050  }
1051 
1057  private function footerLinkTitle( $desc, $page ) {
1058  // If the link description has been set to "-" in the default language,
1059  if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
1060  // then it is disabled, for all languages.
1061  return null;
1062  }
1063  // Otherwise, we display the link for the user, described in their
1064  // language (which may or may not be the same as the default language),
1065  // but we make the link target be the one site-wide page.
1066  $title = Title::newFromText( $this->msg( $page )->inContentLanguage()->text() );
1067 
1068  return $title ?: null;
1069  }
1070 
1075  function privacyLink() {
1076  return $this->footerLink( 'privacy', 'privacypage' );
1077  }
1078 
1083  function aboutLink() {
1084  return $this->footerLink( 'aboutsite', 'aboutpage' );
1085  }
1086 
1091  function disclaimerLink() {
1092  return $this->footerLink( 'disclaimers', 'disclaimerpage' );
1093  }
1094 
1102  function editUrlOptions() {
1103  $options = [ 'action' => 'edit' ];
1104 
1105  if ( !$this->getOutput()->isRevisionCurrent() ) {
1106  $options['oldid'] = intval( $this->getOutput()->getRevisionId() );
1107  }
1108 
1109  return $options;
1110  }
1111 
1116  function showEmailUser( $id ) {
1117  if ( $id instanceof User ) {
1118  $targetUser = $id;
1119  } else {
1120  $targetUser = User::newFromId( $id );
1121  }
1122 
1123  # The sending user must have a confirmed email address and the receiving
1124  # user must accept emails from the sender.
1125  return $this->getUser()->canSendEmail()
1126  && SpecialEmailUser::validateTarget( $targetUser, $this->getUser() ) === '';
1127  }
1128 
1140  function getSkinStylePath( $name ) {
1141  if ( $this->stylename === null ) {
1142  $class = static::class;
1143  throw new MWException( "$class::\$stylename must be set to use getSkinStylePath()" );
1144  }
1145 
1146  return $this->getConfig()->get( 'StylePath' ) . "/{$this->stylename}/$name";
1147  }
1148 
1149  /* these are used extensively in SkinTemplate, but also some other places */
1150 
1155  static function makeMainPageUrl( $urlaction = '' ) {
1157  self::checkTitle( $title, '' );
1158 
1159  return $title->getLinkURL( $urlaction );
1160  }
1161 
1173  static function makeSpecialUrl( $name, $urlaction = '', $proto = null ) {
1175  if ( is_null( $proto ) ) {
1176  return $title->getLocalURL( $urlaction );
1177  } else {
1178  return $title->getFullURL( $urlaction, false, $proto );
1179  }
1180  }
1181 
1188  static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) {
1189  $title = SpecialPage::getSafeTitleFor( $name, $subpage );
1190  return $title->getLocalURL( $urlaction );
1191  }
1192 
1199  static function makeI18nUrl( $name, $urlaction = '' ) {
1200  wfDeprecated( __METHOD__, '1.35' );
1201  $title = Title::newFromText( wfMessage( $name )->inContentLanguage()->text() );
1202  self::checkTitle( $title, $name );
1203  return $title->getLocalURL( $urlaction );
1204  }
1205 
1211  static function makeUrl( $name, $urlaction = '' ) {
1212  $title = Title::newFromText( $name );
1213  self::checkTitle( $title, $name );
1214 
1215  return $title->getLocalURL( $urlaction );
1216  }
1217 
1224  static function makeInternalOrExternalUrl( $name ) {
1225  if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $name ) ) {
1226  return $name;
1227  } else {
1228  return self::makeUrl( $name );
1229  }
1230  }
1231 
1240  static function makeNSUrl( $name, $urlaction = '', $namespace = NS_MAIN ) {
1241  wfDeprecated( __METHOD__, '1.35' );
1242  $title = Title::makeTitleSafe( $namespace, $name );
1243  self::checkTitle( $title, $name );
1244 
1245  return $title->getLocalURL( $urlaction );
1246  }
1247 
1254  static function makeUrlDetails( $name, $urlaction = '' ) {
1255  $title = Title::newFromText( $name );
1256  self::checkTitle( $title, $name );
1257 
1258  return [
1259  'href' => $title->getLocalURL( $urlaction ),
1260  'exists' => $title->isKnown(),
1261  ];
1262  }
1263 
1270  static function makeKnownUrlDetails( $name, $urlaction = '' ) {
1271  $title = Title::newFromText( $name );
1272  self::checkTitle( $title, $name );
1273 
1274  return [
1275  'href' => $title->getLocalURL( $urlaction ),
1276  'exists' => true
1277  ];
1278  }
1279 
1286  static function checkTitle( &$title, $name ) {
1287  if ( !is_object( $title ) ) {
1288  $title = Title::newFromText( $name );
1289  if ( !is_object( $title ) ) {
1290  $title = Title::newFromText( '--error: link target missing--' );
1291  }
1292  }
1293  }
1294 
1316  public function buildSidebar() {
1317  $services = MediaWikiServices::getInstance();
1318  $callback = function ( $old = null, &$ttl = null ) {
1319  $bar = [];
1320  $this->addToSidebar( $bar, 'sidebar' );
1321  Hooks::run( 'SkinBuildSidebar', [ $this, &$bar ] );
1322  $msgCache = MediaWikiServices::getInstance()->getMessageCache();
1323  if ( $msgCache->isDisabled() ) {
1324  $ttl = WANObjectCache::TTL_UNCACHEABLE; // bug T133069
1325  }
1326 
1327  return $bar;
1328  };
1329 
1330  $msgCache = $services->getMessageCache();
1331  $wanCache = $services->getMainWANObjectCache();
1332  $config = $this->getConfig();
1333 
1334  $sidebar = $config->get( 'EnableSidebarCache' )
1335  ? $wanCache->getWithSetCallback(
1336  $wanCache->makeKey( 'sidebar', $this->getLanguage()->getCode() ),
1337  $config->get( 'SidebarCacheExpiry' ),
1338  $callback,
1339  [
1340  'checkKeys' => [
1341  // Unless there is both no exact $code override nor an i18n definition
1342  // in the software, the only MediaWiki page to check is for $code.
1343  $msgCache->getCheckKey( $this->getLanguage()->getCode() )
1344  ],
1345  'lockTSE' => 30
1346  ]
1347  )
1348  : $callback();
1349 
1350  // Apply post-processing to the cached value
1351  Hooks::run( 'SidebarBeforeOutput', [ $this, &$sidebar ] );
1352 
1353  return $sidebar;
1354  }
1355 
1365  public function addToSidebar( &$bar, $message ) {
1366  $this->addToSidebarPlain( $bar, $this->msg( $message )->inContentLanguage()->plain() );
1367  }
1368 
1376  function addToSidebarPlain( &$bar, $text ) {
1377  $lines = explode( "\n", $text );
1378 
1379  $heading = '';
1380  $config = $this->getConfig();
1381  $messageTitle = $config->get( 'EnableSidebarCache' )
1382  ? Title::newMainPage() : $this->getTitle();
1383 
1384  foreach ( $lines as $line ) {
1385  if ( strpos( $line, '*' ) !== 0 ) {
1386  continue;
1387  }
1388  $line = rtrim( $line, "\r" ); // for Windows compat
1389 
1390  if ( strpos( $line, '**' ) !== 0 ) {
1391  $heading = trim( $line, '* ' );
1392  if ( !array_key_exists( $heading, $bar ) ) {
1393  $bar[$heading] = [];
1394  }
1395  } else {
1396  $line = trim( $line, '* ' );
1397 
1398  if ( strpos( $line, '|' ) !== false ) { // sanity check
1399  $line = MessageCache::singleton()->transform( $line, false, null, $messageTitle );
1400  $line = array_map( 'trim', explode( '|', $line, 2 ) );
1401  if ( count( $line ) !== 2 ) {
1402  // Second sanity check, could be hit by people doing
1403  // funky stuff with parserfuncs... (T35321)
1404  continue;
1405  }
1406 
1407  $extraAttribs = [];
1408 
1409  $msgLink = $this->msg( $line[0] )->title( $messageTitle )->inContentLanguage();
1410  if ( $msgLink->exists() ) {
1411  $link = $msgLink->text();
1412  if ( $link == '-' ) {
1413  continue;
1414  }
1415  } else {
1416  $link = $line[0];
1417  }
1418  $msgText = $this->msg( $line[1] )->title( $messageTitle );
1419  if ( $msgText->exists() ) {
1420  $text = $msgText->text();
1421  } else {
1422  $text = $line[1];
1423  }
1424 
1425  if ( preg_match( '/^(?i:' . wfUrlProtocols() . ')/', $link ) ) {
1426  $href = $link;
1427 
1428  // Parser::getExternalLinkAttribs won't work here because of the Namespace things
1429  if ( $config->get( 'NoFollowLinks' ) &&
1430  !wfMatchesDomainList( $href, $config->get( 'NoFollowDomainExceptions' ) )
1431  ) {
1432  $extraAttribs['rel'] = 'nofollow';
1433  }
1434 
1435  if ( $config->get( 'ExternalLinkTarget' ) ) {
1436  $extraAttribs['target'] = $config->get( 'ExternalLinkTarget' );
1437  }
1438  } else {
1439  $title = Title::newFromText( $link );
1440 
1441  if ( $title ) {
1442  $title = $title->fixSpecialName();
1443  $href = $title->getLinkURL();
1444  } else {
1445  $href = 'INVALID-TITLE';
1446  }
1447  }
1448 
1449  $bar[$heading][] = array_merge( [
1450  'text' => $text,
1451  'href' => $href,
1452  'id' => Sanitizer::escapeIdForAttribute( 'n-' . strtr( $line[1], ' ', '-' ) ),
1453  'active' => false,
1454  ], $extraAttribs );
1455  } else {
1456  continue;
1457  }
1458  }
1459  }
1460 
1461  return $bar;
1462  }
1463 
1469  function getNewtalks() {
1470  $newMessagesAlert = '';
1471  $user = $this->getUser();
1472  $newtalks = $user->getNewMessageLinks();
1473  $out = $this->getOutput();
1474  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1475 
1476  // Allow extensions to disable or modify the new messages alert
1477  if ( !Hooks::run( 'GetNewMessagesAlert', [ &$newMessagesAlert, $newtalks, $user, $out ] ) ) {
1478  return '';
1479  }
1480  if ( $newMessagesAlert ) {
1481  return $newMessagesAlert;
1482  }
1483 
1484  if ( count( $newtalks ) == 1 && WikiMap::isCurrentWikiId( $newtalks[0]['wiki'] ) ) {
1485  $uTalkTitle = $user->getTalkPage();
1486  $lastSeenRev = $newtalks[0]['rev'] ?? null;
1487  $nofAuthors = 0;
1488  if ( $lastSeenRev !== null ) {
1489  $plural = true; // Default if we have a last seen revision: if unknown, use plural
1490  $latestRev = Revision::newFromTitle( $uTalkTitle, false, Revision::READ_NORMAL );
1491  if ( $latestRev !== null ) {
1492  // Singular if only 1 unseen revision, plural if several unseen revisions.
1493  $plural = $latestRev->getParentId() !== $lastSeenRev->getId();
1494  $nofAuthors = $uTalkTitle->countAuthorsBetween(
1495  $lastSeenRev, $latestRev, 10, 'include_new' );
1496  }
1497  } else {
1498  // Singular if no revision -> diff link will show latest change only in any case
1499  $plural = false;
1500  }
1501  $plural = $plural ? 999 : 1;
1502  // 999 signifies "more than one revision". We don't know how many, and even if we did,
1503  // the number of revisions or authors is not necessarily the same as the number of
1504  // "messages".
1505  $newMessagesLink = $linkRenderer->makeKnownLink(
1506  $uTalkTitle,
1507  $this->msg( 'newmessageslinkplural' )->params( $plural )->text(),
1508  [],
1509  $uTalkTitle->isRedirect() ? [ 'redirect' => 'no' ] : []
1510  );
1511 
1512  $newMessagesDiffLink = $linkRenderer->makeKnownLink(
1513  $uTalkTitle,
1514  $this->msg( 'newmessagesdifflinkplural' )->params( $plural )->text(),
1515  [],
1516  $lastSeenRev !== null
1517  ? [ 'oldid' => $lastSeenRev->getId(), 'diff' => 'cur' ]
1518  : [ 'diff' => 'cur' ]
1519  );
1520 
1521  if ( $nofAuthors >= 1 && $nofAuthors <= 10 ) {
1522  $newMessagesAlert = $this->msg(
1523  'youhavenewmessagesfromusers',
1524  $newMessagesLink,
1525  $newMessagesDiffLink
1526  )->numParams( $nofAuthors, $plural );
1527  } else {
1528  // $nofAuthors === 11 signifies "11 or more" ("more than 10")
1529  $newMessagesAlert = $this->msg(
1530  $nofAuthors > 10 ? 'youhavenewmessagesmanyusers' : 'youhavenewmessages',
1531  $newMessagesLink,
1532  $newMessagesDiffLink
1533  )->numParams( $plural );
1534  }
1535  $newMessagesAlert = $newMessagesAlert->text();
1536  # Disable CDN cache
1537  $out->setCdnMaxage( 0 );
1538  } elseif ( count( $newtalks ) ) {
1539  $sep = $this->msg( 'newtalkseparator' )->escaped();
1540  $msgs = [];
1541 
1542  foreach ( $newtalks as $newtalk ) {
1543  $msgs[] = Xml::element(
1544  'a',
1545  [ 'href' => $newtalk['link'] ], $newtalk['wiki']
1546  );
1547  }
1548  $parts = implode( $sep, $msgs );
1549  $newMessagesAlert = $this->msg( 'youhavenewmessagesmulti' )->rawParams( $parts )->escaped();
1550  $out->setCdnMaxage( 0 );
1551  }
1552 
1553  return $newMessagesAlert;
1554  }
1555 
1563  private function getCachedNotice( $name ) {
1564  $config = $this->getConfig();
1565 
1566  if ( $name === 'default' ) {
1567  // special case
1568  $notice = $config->get( 'SiteNotice' );
1569  if ( empty( $notice ) ) {
1570  return false;
1571  }
1572  } else {
1573  $msg = $this->msg( $name )->inContentLanguage();
1574  if ( $msg->isBlank() ) {
1575  return '';
1576  } elseif ( $msg->isDisabled() ) {
1577  return false;
1578  }
1579  $notice = $msg->plain();
1580  }
1581 
1582  $services = MediaWikiServices::getInstance();
1583  $cache = $services->getMainWANObjectCache();
1584  $parsed = $cache->getWithSetCallback(
1585  // Use the extra hash appender to let eg SSL variants separately cache
1586  // Key is verified with md5 hash of unparsed wikitext
1587  $cache->makeKey( $name, $config->get( 'RenderHashAppend' ), md5( $notice ) ),
1588  // TTL in seconds
1589  600,
1590  function () use ( $notice ) {
1591  return $this->getOutput()->parseAsInterface( $notice );
1592  }
1593  );
1594 
1595  $contLang = $services->getContentLanguage();
1596  return Html::rawElement(
1597  'div',
1598  [
1599  'id' => 'localNotice',
1600  'lang' => $contLang->getHtmlCode(),
1601  'dir' => $contLang->getDir()
1602  ],
1603  $parsed
1604  );
1605  }
1606 
1612  function getSiteNotice() {
1613  $siteNotice = '';
1614 
1615  if ( Hooks::run( 'SiteNoticeBefore', [ &$siteNotice, $this ] ) ) {
1616  if ( is_object( $this->getUser() ) && $this->getUser()->isLoggedIn() ) {
1617  $siteNotice = $this->getCachedNotice( 'sitenotice' );
1618  } else {
1619  $anonNotice = $this->getCachedNotice( 'anonnotice' );
1620  if ( $anonNotice === false ) {
1621  $siteNotice = $this->getCachedNotice( 'sitenotice' );
1622  } else {
1623  $siteNotice = $anonNotice;
1624  }
1625  }
1626  if ( $siteNotice === false ) {
1627  $siteNotice = $this->getCachedNotice( 'default' );
1628  }
1629  }
1630 
1631  Hooks::run( 'SiteNoticeAfter', [ &$siteNotice, $this ] );
1632  return $siteNotice;
1633  }
1634 
1648  public function doEditSectionLink( Title $nt, $section, $tooltip, Language $lang ) {
1649  // HTML generated here should probably have userlangattributes
1650  // added to it for LTR text on RTL pages
1651 
1652  $attribs = [];
1653  if ( !is_null( $tooltip ) ) {
1654  $attribs['title'] = $this->msg( 'editsectionhint' )->rawParams( $tooltip )
1655  ->inLanguage( $lang )->text();
1656  }
1657 
1658  $links = [
1659  'editsection' => [
1660  'text' => $this->msg( 'editsection' )->inLanguage( $lang )->text(),
1661  'targetTitle' => $nt,
1662  'attribs' => $attribs,
1663  'query' => [ 'action' => 'edit', 'section' => $section ]
1664  ]
1665  ];
1666 
1667  Hooks::run( 'SkinEditSectionLinks', [ $this, $nt, $section, $tooltip, &$links, $lang ] );
1668 
1669  $result = '<span class="mw-editsection"><span class="mw-editsection-bracket">[</span>';
1670 
1671  $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer();
1672  $linksHtml = [];
1673  foreach ( $links as $k => $linkDetails ) {
1674  $linksHtml[] = $linkRenderer->makeKnownLink(
1675  $linkDetails['targetTitle'],
1676  $linkDetails['text'],
1677  $linkDetails['attribs'],
1678  $linkDetails['query']
1679  );
1680  }
1681 
1682  $result .= implode(
1683  '<span class="mw-editsection-divider">'
1684  . $this->msg( 'pipe-separator' )->inLanguage( $lang )->escaped()
1685  . '</span>',
1686  $linksHtml
1687  );
1688 
1689  $result .= '<span class="mw-editsection-bracket">]</span></span>';
1690  return $result;
1691  }
1692 
1693 }
showEmailUser( $id)
Definition: Skin.php:1116
static makeUrlDetails( $name, $urlaction='')
these return an array with the &#39;href&#39; and boolean &#39;exists&#39;
Definition: Skin.php:1254
static makeI18nUrl( $name, $urlaction='')
Definition: Skin.php:1199
makeFooterIcon( $icon, $withImage='withImage')
Renders a $wgFooterIcons icon according to the method&#39;s arguments.
Definition: Skin.php:998
wfUrlProtocols( $includeProtocolRelative=true)
Returns a regular expression of url protocols.
lastModified()
Get the timestamp of the latest revision, formatted in user language.
Definition: Skin.php:945
footerLinkTitle( $desc, $page)
Definition: Skin.php:1057
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:231
static normalizeKey( $key)
Normalize a skin preference value to a form that can be loaded.
Definition: Skin.php:104
static getTimestampFromId( $title, $id, $flags=0)
Get rev_timestamp from rev_id, without loading the rest of the row.
Definition: Revision.php:1061
afterContentHook()
This runs a hook to allow extensions placing their stuff after content and article metadata (e...
Definition: Skin.php:649
setRelevantUser( $u)
Set the "relevant" user.
Definition: Skin.php:355
getPoweredBy()
Gets the powered by MediaWiki icon.
Definition: Skin.php:922
getNewtalks()
Gets new talk page messages for the current user and returns an appropriate alert message (or an empt...
Definition: Skin.php:1469
const NS_MAIN
Definition: Defines.php:60
static makeSpecialUrl( $name, $urlaction='', $proto=null)
Make a URL for a Special Page using the given query and protocol.
Definition: Skin.php:1173
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:646
static isIP( $name)
Does the string match an anonymous IP address?
Definition: User.php:947
buildSidebar()
Build an array that represents the sidebar(s), the navigation bar among them.
Definition: Skin.php:1316
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
privacyLink()
Gets the link to the wiki&#39;s privacy policy page.
Definition: Skin.php:1075
if(!isset( $args[0])) $lang
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:209
doEditSectionLink(Title $nt, $section, $tooltip, Language $lang)
Create a section edit link.
Definition: Skin.php:1648
initPage(OutputPage $out)
Definition: Skin.php:165
editUrlOptions()
Return URL options for the &#39;edit page&#39; link.
Definition: Skin.php:1102
getLogo()
URL to the logo.
Definition: Skin.php:503
static getSkinNames()
Fetch the set of available skins.
Definition: Skin.php:57
getCopyrightIcon()
Definition: Skin.php:892
static makeConfigSetScript(array $configuration)
Returns JS code which will set the MediaWiki configuration array to the given value.
getCachedNotice( $name)
Get a cached notice.
Definition: Skin.php:1563
static newFromTitle(LinkTarget $linkTarget, $id=0, $flags=0)
Load either the current, or a specified, revision that&#39;s attached to a given link target...
Definition: Revision.php:139
shouldPreloadLogo()
Whether the logo should be preloaded with an HTTP link header or not.
Definition: Skin.php:516
getCategories()
Definition: Skin.php:614
getSiteNotice()
Get the site notice.
Definition: Skin.php:1612
static getHTMLDebugLog()
Generate debug log in HTML for displaying at the bottom of the main content area. ...
Definition: MWDebug.php:478
getPageClasses( $title)
TODO: document.
Definition: Skin.php:441
addToBodyAttributes( $out, &$bodyAttrs)
This will be called by OutputPage::headElement when it is creating the "<body>" tag, skins can override it if they have a need to add in any body attributes or classes of their own.
Definition: Skin.php:495
The User object encapsulates all of the user-specific settings (user_id, name, rights, email address, options, last login time).
Definition: User.php:51
Class representing a list of titles The execute() method checks them all for existence and adds them ...
Definition: LinkBatch.php:34
preloadExistence()
Preload the existence of three commonly-requested pages in a single query.
Definition: Skin.php:265
footerLink( $desc, $page)
Returns an HTML link for use in the footer.
Definition: Skin.php:1039
$modules
wfMatchesDomainList( $url, $domains)
Check whether a given URL has a domain that occurs in a given set of domains.
$mRelevantTitle
Definition: Skin.php:44
static checkTitle(&$title, $name)
make sure we have some title to operate on
Definition: Skin.php:1286
mainPageLink()
Gets the link to the wiki&#39;s main page.
Definition: Skin.php:1023
static escapeIdForAttribute( $id, $mode=self::ID_PRIMARY)
Given a section name or other user-generated or otherwise unsafe string, escapes it to be a valid HTM...
Definition: Sanitizer.php:1257
drawCategoryBrowser( $tree)
Render the array as a series of links.
Definition: Skin.php:590
getRelevantTitle()
Return the "relevant" title.
Definition: Skin.php:346
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
subPageSubtitle( $out=null)
Definition: Skin.php:772
getCategoryLinks()
Definition: Skin.php:523
disclaimerLink()
Gets the link to the wiki&#39;s general disclaimers page.
Definition: Skin.php:1091
getContext()
Get the base IContextSource object.
$cache
Definition: mcc.php:33
getSearchLink()
Definition: Skin.php:831
$mRelevantUser
Definition: Skin.php:45
const NS_CATEGORY
Definition: Defines.php:74
static makeVariablesScript( $data, $nonce=null)
Definition: Skin.php:402
static makeExternalLink( $url, $text, $escape=true, $linktype='', $attribs=[], $title=null)
Make an external link.
Definition: Linker.php:848
generateDebugHTML()
Generate debug data HTML for displaying at the bottom of the main content area.
Definition: Skin.php:675
setRelevantTitle( $t)
Set the "relevant" title.
Definition: Skin.php:332
getHtmlElementAttributes()
Return values for <html> element.
Definition: Skin.php:479
static escapeClass( $class)
Given a value, escape it so that it can be used as a CSS class and return it.
Definition: Sanitizer.php:1380
getRelevantUser()
Return the "relevant" user.
Definition: Skin.php:367
aboutLink()
Gets the link to the wiki&#39;s about page.
Definition: Skin.php:1083
addToSidebarPlain(&$bar, $text)
Add content from plain text.
Definition: Skin.php:1376
addToSidebar(&$bar, $message)
Add content from a sidebar system message Currently only used for MediaWiki:Sidebar (but may be used ...
Definition: Skin.php:1365
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don&#39;t need a full Title object...
Definition: SpecialPage.php:83
logoText( $align='')
Definition: Skin.php:973
static makeKnownUrlDetails( $name, $urlaction='')
Make URL details where the article exists (or at least it&#39;s convenient to think so) ...
Definition: Skin.php:1270
static makeInlineScript( $script, $nonce=null)
Returns an HTML script tag that runs given JS code after startup and base modules.
static makeUrl( $name, $urlaction='')
Definition: Skin.php:1211
getDefaultModules()
Defines the ResourceLoader modules that should be added to the skin It is recommended that skins wish...
Definition: Skin.php:179
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:610
printSource()
Text with the permalink to the source page, usually shown on the footer of a printed page...
Definition: Skin.php:706
static newFromId( $id)
Static factory method for creation from a given user ID.
Definition: User.php:560
string $stylename
Stylesheets set to use.
Definition: Skin.php:51
$fallback
Definition: MessagesAb.php:11
$lines
Definition: router.php:61
static isCurrentWikiId( $wikiId)
Definition: WikiMap.php:313
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
wfExpandIRI( $url)
Take a URL, make sure it&#39;s expanded to fully qualified, and replace any encoded non-ASCII Unicode cha...
isRevisionCurrent()
Whether the revision displayed is the latest revision of the page.
Definition: Skin.php:323
$wgDefaultSkin
Default skin, for new users and anonymous visitors.
static makeNSUrl( $name, $urlaction='', $namespace=NS_MAIN)
this can be passed the NS number as defined in Language.php
Definition: Skin.php:1240
$wgSkipSkins
Specify the names of skins that should not be presented in the list of available skins in user prefer...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
static getSkinNameMessages()
Fetch the skinname messages for available skins.
Definition: Skin.php:67
getCopyright( $type='detect')
Definition: Skin.php:849
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Definition: Xml.php:41
$wgFallbackSkin
Fallback skin used when the skin defined by $wgDefaultSkin can&#39;t be found.
static validateTarget( $target, User $sender)
Validate target User.
getUndeleteLink()
Definition: Skin.php:724
$line
Definition: mcc.php:119
static makeInternalOrExternalUrl( $name)
If url string starts with http, consider as external URL, else internal.
Definition: Skin.php:1224
getSkinStylePath( $name)
Return a fully resolved style path URL to images or styles stored in the current skin&#39;s folder...
Definition: Skin.php:1140
static getSafeTitleFor( $name, $subpage=false)
Get a localised Title object for a page name with a possibly unvalidated subpage. ...
static getDynamicStylesheetQuery()
Get the query to generate a dynamic stylesheet.
Definition: Skin.php:418
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:536
setupSkinUserCss(OutputPage $out)
Hook point for adding style modules to OutputPage.
Definition: Skin.php:432
static makeMainPageUrl( $urlaction='')
Definition: Skin.php:1155
$searchPage
getRevisionId()
Get the current revision ID.
Definition: Skin.php:313
outputPage()
Outputs the HTML generated by other functions.
escapeSearchLink()
Definition: Skin.php:840
getSkinName()
Definition: Skin.php:158
static getAllowedSkins()
Fetch the list of user-selectable skins in regards to $wgSkipSkins.
Definition: Skin.php:83
__construct( $skinname=null)
Definition: Skin.php:149
bottomScripts()
This gets called shortly before the "</body>" tag.
Definition: Skin.php:684
return true
Definition: router.php:92
static singleton()
Get the singleton instance of this class.
static makeSpecialUrlSubpage( $name, $subpage, $urlaction='')
Definition: Skin.php:1188
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
string null $skinname
Definition: Skin.php:42
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:317