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