read() ) ) { // Skip non-PHP files, hidden files, and '.dep' includes $matches = array(); if( preg_match( '/^([^.]*)\.php$/', $file, $matches ) ) { $aSkin = $matches[1]; $wgValidSkinNames[strtolower($aSkin)] = $aSkin; } } $skinDir->close(); $skinsInitialised = true; wfProfileOut( __METHOD__ . '-init' ); } return $wgValidSkinNames; } /** * Fetch the list of usable skins in regards to $wgSkipSkins. * Useful for Special:Preferences and other places where you * only want to show skins users _can_ use. * @return array of strings */ public static function getUsableSkins() { global $wgSkipSkins; $usableSkins = self::getSkinNames(); foreach ( $wgSkipSkins as $skip ) { unset( $usableSkins[$skip] ); } return $usableSkins; } /** * Normalize a skin preference value to a form that can be loaded. * If a skin can't be found, it will fall back to the configured * default (or the old 'Classic' skin if that's broken). * @param string $key * @return string * @static */ static function normalizeKey( $key ) { global $wgDefaultSkin; $skinNames = Skin::getSkinNames(); if( $key == '' ) { // Don't return the default immediately; // in a misconfiguration we need to fall back. $key = $wgDefaultSkin; } if( isset( $skinNames[$key] ) ) { return $key; } // Older versions of the software used a numeric setting // in the user preferences. $fallback = array( 0 => $wgDefaultSkin, 1 => 'nostalgia', 2 => 'cologneblue' ); if( isset( $fallback[$key] ) ){ $key = $fallback[$key]; } if( isset( $skinNames[$key] ) ) { return $key; } else { return 'monobook'; } } /** * Factory method for loading a skin of a given type * @param string $key 'monobook', 'standard', etc * @return Skin * @static */ static function &newFromKey( $key ) { global $wgStyleDirectory; $key = Skin::normalizeKey( $key ); $skinNames = Skin::getSkinNames(); $skinName = $skinNames[$key]; $className = 'Skin'.ucfirst($key); # Grab the skin class and initialise it. if ( !class_exists( $className ) ) { // Preload base classes to work around APC/PHP5 bug $deps = "{$wgStyleDirectory}/{$skinName}.deps.php"; if( file_exists( $deps ) ) include_once( $deps ); require_once( "{$wgStyleDirectory}/{$skinName}.php" ); # Check if we got if not failback to default skin if( !class_exists( $className ) ) { # DO NOT die if the class isn't found. This breaks maintenance # scripts and can cause a user account to be unrecoverable # except by SQL manipulation if a previously valid skin name # is no longer valid. wfDebug( "Skin class does not exist: $className\n" ); $className = 'SkinMonobook'; require_once( "{$wgStyleDirectory}/MonoBook.php" ); } } $skin = new $className; return $skin; } /** @return string path to the skin stylesheet */ function getStylesheet() { return 'common/wikistandard.css'; } /** @return string skin name */ public function getSkinName() { return $this->skinname; } function qbSetting() { global $wgOut, $wgUser; if ( $wgOut->isQuickbarSuppressed() ) { return 0; } $q = $wgUser->getOption( 'quickbar', 0 ); return $q; } function initPage( OutputPage $out ) { global $wgFavicon, $wgAppleTouchIcon; wfProfileIn( __METHOD__ ); # Generally the order of the favicon and apple-touch-icon links # should not matter, but Konqueror (3.5.9 at least) incorrectly # uses whichever one appears later in the HTML source. Make sure # apple-touch-icon is specified first to avoid this. if( false !== $wgAppleTouchIcon ) { $out->addLink( array( 'rel' => 'apple-touch-icon', 'href' => $wgAppleTouchIcon ) ); } if( false !== $wgFavicon ) { $out->addLink( array( 'rel' => 'shortcut icon', 'href' => $wgFavicon ) ); } # OpenSearch description link $out->addLink( array( 'rel' => 'search', 'type' => 'application/opensearchdescription+xml', 'href' => wfScript( 'opensearch_desc' ), 'title' => wfMsgForContent( 'opensearch-desc' ), )); $this->addMetadataLinks( $out ); $this->mRevisionId = $out->mRevisionId; $this->preloadExistence(); wfProfileOut( __METHOD__ ); } /** * Preload the existence of three commonly-requested pages in a single query */ function preloadExistence() { global $wgUser; // User/talk link $titles = array( $wgUser->getUserPage(), $wgUser->getTalkPage() ); // Other tab link if ( $this->mTitle->getNamespace() == NS_SPECIAL ) { // nothing } elseif ( $this->mTitle->isTalkPage() ) { $titles[] = $this->mTitle->getSubjectPage(); } else { $titles[] = $this->mTitle->getTalkPage(); } $lb = new LinkBatch( $titles ); $lb->execute(); } function addMetadataLinks( OutputPage $out ) { global $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf; global $wgRightsPage, $wgRightsUrl; if( $out->isArticleRelated() ) { # note: buggy CC software only reads first "meta" link if( $wgEnableCreativeCommonsRdf ) { $out->addMetadataLink( array( 'title' => 'Creative Commons', 'type' => 'application/rdf+xml', 'href' => $this->mTitle->getLocalURL( 'action=creativecommons' ) ) ); } if( $wgEnableDublinCoreRdf ) { $out->addMetadataLink( array( 'title' => 'Dublin Core', 'type' => 'application/rdf+xml', 'href' => $this->mTitle->getLocalURL( 'action=dublincore' ) ) ); } } $copyright = ''; if( $wgRightsPage ) { $copy = Title::newFromText( $wgRightsPage ); if( $copy ) { $copyright = $copy->getLocalURL(); } } if( !$copyright && $wgRightsUrl ) { $copyright = $wgRightsUrl; } if( $copyright ) { $out->addLink( array( 'rel' => 'copyright', 'href' => $copyright ) ); } } /** * Set some local variables */ protected function setMembers(){ global $wgUser; $this->mUser = $wgUser; $this->userpage = $wgUser->getUserPage()->getPrefixedText(); $this->usercss = false; } /** * Set the title * @param Title $t The title to use */ public function setTitle( $t ) { $this->mTitle = $t; } /** Get the title */ public function getTitle() { return $this->mTitle; } function outputPage( OutputPage $out ) { global $wgDebugComments; wfProfileIn( __METHOD__ ); $this->setMembers(); $this->initPage( $out ); // See self::afterContentHook() for documentation $afterContent = $this->afterContentHook(); $out->out( $out->headElement( $this ) ); $out->out( "\ngetBodyOptions(); foreach ( $ops as $name => $val ) { $out->out( " $name='$val'" ); } $out->out( ">\n" ); if ( $wgDebugComments ) { $out->out( "\n" ); } $out->out( $this->beforeContent() ); $out->out( $out->mBodytext . "\n" ); $out->out( $this->afterContent() ); $out->out( $afterContent ); $out->out( $this->bottomScripts() ); $out->out( wfReportTime() ); $out->out( "\n" ); wfProfileOut( __METHOD__ ); } static function makeVariablesScript( $data ) { global $wgJsMimeType; $r = array( "\n"; return implode( "\n\t\t", $r ); } /** * Make a \n"; wfRunHooks( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) ); return $bottomScriptText; } /** @return string Retrievied from HTML text */ function printSource() { $url = htmlspecialchars( $this->mTitle->getFullURL() ); return wfMsg( 'retrievedfrom', ''.$url.'' ); } function printFooter() { return "

" . $this->printSource() . "

\n\n

" . $this->pageStats() . "

\n"; } /** overloaded by derived classes */ function doAfterContent() { return ''; } function pageTitleLinks() { global $wgOut, $wgUser, $wgRequest, $wgLang; $oldid = $wgRequest->getVal( 'oldid' ); $diff = $wgRequest->getVal( 'diff' ); $action = $wgRequest->getText( 'action' ); $s[] = $this->printableLink(); $disclaimer = $this->disclaimerLink(); # may be empty if( $disclaimer ) { $s[] = $disclaimer; } $privacy = $this->privacyLink(); # may be empty too if( $privacy ) { $s[] = $privacy; } if ( $wgOut->isArticleRelated() ) { if ( $this->mTitle->getNamespace() == NS_FILE ) { $name = $this->mTitle->getDBkey(); $image = wfFindFile( $this->mTitle ); if( $image ) { $link = htmlspecialchars( $image->getURL() ); $style = $this->getInternalLinkAttributes( $link, $name ); $s[] = "{$name}"; } } } if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) { $s[] .= $this->link( $this->mTitle, wfMsg( 'currentrev' ), array(), array(), array( 'known', 'noclasses' ) ); } if ( $wgUser->getNewtalk() ) { # do not show "You have new messages" text when we are viewing our # own talk page if( !$this->mTitle->equals( $wgUser->getTalkPage() ) ) { $tl = $this->link( $wgUser->getTalkPage(), wfMsgHtml( 'newmessageslink' ), array(), array( 'redirect' => 'no' ), array( 'known', 'noclasses' ) ); $dl = $this->link( $wgUser->getTalkPage(), wfMsgHtml( 'newmessagesdifflink' ), array(), array( 'diff' => 'cur' ), array( 'known', 'noclasses' ) ); $s[] = ''. wfMsg( 'youhavenewmessages', $tl, $dl ) . ''; # disable caching $wgOut->setSquidMaxage( 0 ); $wgOut->enableClientCache( false ); } } $undelete = $this->getUndeleteLink(); if( !empty( $undelete ) ) { $s[] = $undelete; } return $wgLang->pipeList( $s ); } function getUndeleteLink() { global $wgUser, $wgContLang, $wgLang, $wgRequest; $action = $wgRequest->getVal( 'action', 'view' ); if ( $wgUser->isAllowed( 'deletedhistory' ) && ( $this->mTitle->getArticleId() == 0 || $action == 'history' ) ) { $n = $this->mTitle->isDeleted(); if ( $n ) { if ( $wgUser->isAllowed( 'undelete' ) ) { $msg = 'thisisdeleted'; } else { $msg = 'viewdeleted'; } return wfMsg( $msg, $this->link( SpecialPage::getTitleFor( 'Undelete', $this->mTitle->getPrefixedDBkey() ), wfMsgExt( 'restorelink', array( 'parsemag', 'escape' ), $wgLang->formatNum( $n ) ), array(), array(), array( 'known', 'noclasses' ) ) ); } } return ''; } function printableLink() { global $wgOut, $wgFeedClasses, $wgRequest, $wgLang; $s = array(); if ( !$wgRequest->getBool( 'printable' ) ) { $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' ); $s[] = "" . wfMsg( 'printableversion' ) . ''; } if( $wgOut->isSyndicated() ) { foreach( $wgFeedClasses as $format => $class ) { $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" ); $s[] = "" . wfMsgHtml( "feed-$format" ) . ""; } } return $wgLang->pipeList( $s ); } function pageTitle() { global $wgOut; $s = '

' . $wgOut->getPageTitle() . '

'; return $s; } function pageSubtitle() { global $wgOut; $sub = $wgOut->getSubtitle(); if ( '' == $sub ) { global $wgExtraSubtitle; $sub = wfMsgExt( 'tagline', 'parsemag' ) . $wgExtraSubtitle; } $subpages = $this->subPageSubtitle(); $sub .= !empty( $subpages ) ? "

$subpages" : ''; $s = "

{$sub}

\n"; return $s; } function subPageSubtitle() { $subpages = ''; if( !wfRunHooks( 'SkinSubPageSubtitle', array( &$subpages ) ) ) return $subpages; global $wgOut; if( $wgOut->isArticle() && MWNamespace::hasSubpages( $this->mTitle->getNamespace() ) ) { $ptext = $this->mTitle->getPrefixedText(); if( preg_match( '/\//', $ptext ) ) { $links = explode( '/', $ptext ); array_pop( $links ); $c = 0; $growinglink = ''; $display = ''; foreach( $links as $link ) { $growinglink .= $link; $display .= $link; $linkObj = Title::newFromText( $growinglink ); if( is_object( $linkObj ) && $linkObj->exists() ){ $getlink = $this->link( $linkObj, htmlspecialchars( $display ), array(), array(), array( 'known', 'noclasses' ) ); $c++; if( $c > 1 ) { $subpages .= wfMsgExt( 'pipe-separator', 'escapenoentities' ); } else { $subpages .= '< '; } $subpages .= $getlink; $display = ''; } else { $display .= '/'; } $growinglink .= '/'; } } } return $subpages; } /** * Returns true if the IP should be shown in the header */ function showIPinHeader() { global $wgShowIPinHeader; return $wgShowIPinHeader && session_id() != ''; } function nameAndLogin() { global $wgUser, $wgLang, $wgContLang; $logoutPage = $wgContLang->specialPage( 'Userlogout' ); $ret = ''; if ( $wgUser->isAnon() ) { if( $this->showIPinHeader() ) { $name = wfGetIP(); $talkLink = $this->link( $wgUser->getTalkPage(), $wgLang->getNsText( NS_TALK ) ); $ret .= "$name ($talkLink)"; } else { $ret .= wfMsg( 'notloggedin' ); } $returnTo = $this->mTitle->getPrefixedDBkey(); $query = array(); if ( $logoutPage != $returnTo ) { $query['returnto'] = $returnTo; } $loginlink = $wgUser->isAllowed( 'createaccount' ) ? 'nav-login-createaccount' : 'login'; $ret .= "\n
" . $this->link( SpecialPage::getTitleFor( 'Userlogin' ), wfMsg( $loginlink ), array(), $query ); } else { $returnTo = $this->mTitle->getPrefixedDBkey(); $talkLink = $this->link( $wgUser->getTalkPage(), $wgLang->getNsText( NS_TALK ) ); $ret .= $this->link( $wgUser->getUserPage(), htmlspecialchars( $wgUser->getName() ) ); $ret .= " ($talkLink)
"; $ret .= $wgLang->pipeList( array( $this->link( SpecialPage::getTitleFor( 'Userlogout' ), wfMsg( 'logout' ), array(), array( 'returnto' => $returnTo ) ), $this->specialLink( 'preferences' ), ) ); } $ret = $wgLang->pipeList( array( $ret, $this->link( Title::newFromText( wfMsgForContent( 'helppage' ) ), wfMsg( 'help' ) ), ) ); return $ret; } function getSearchLink() { $searchPage = SpecialPage::getTitleFor( 'Search' ); return $searchPage->getLocalURL(); } function escapeSearchLink() { return htmlspecialchars( $this->getSearchLink() ); } function searchForm() { global $wgRequest, $wgUseTwoButtonsSearchForm; $search = $wgRequest->getText( 'search' ); $s = '
\n" . '\n" . ''; if( $wgUseTwoButtonsSearchForm ) $s .= ' \n"; else $s .= ' \n"; $s .= '
'; // Ensure unique id's for search boxes made after the first $this->searchboxes = $this->searchboxes == '' ? 2 : $this->searchboxes + 1; return $s; } function topLinks() { global $wgOut; $s = array( $this->mainPageLink(), $this->specialLink( 'recentchanges' ) ); if ( $wgOut->isArticleRelated() ) { $s[] = $this->editThisPage(); $s[] = $this->historyLink(); } # Many people don't like this dropdown box #$s[] = $this->specialPagesList(); if( $this->variantLinks() ) { $s[] = $this->variantLinks(); } if( $this->extensionTabLinks() ) { $s[] = $this->extensionTabLinks(); } // FIXME: Is using Language::pipeList impossible here? Do not quite understand the use of the newline return implode( $s, wfMsgExt( 'pipe-separator', 'escapenoentities' ) . "\n" ); } /** * Compatibility for extensions adding functionality through tabs. * Eventually these old skins should be replaced with SkinTemplate-based * versions, sigh... * @return string */ function extensionTabLinks() { $tabs = array(); $out = ''; $s = array(); wfRunHooks( 'SkinTemplateTabs', array( $this, &$tabs ) ); foreach( $tabs as $tab ) { $s[] = Xml::element( 'a', array( 'href' => $tab['href'] ), $tab['text'] ); } if( count( $s ) ) { global $wgLang; $out = wfMsgExt( 'pipe-separator' , 'escapenoentities' ); $out .= $wgLang->pipeList( $s ); } return $out; } /** * Language/charset variant links for classic-style skins * @return string */ function variantLinks() { $s = ''; /* show links to different language variants */ global $wgDisableLangConversion, $wgLang, $wgContLang; $variants = $wgContLang->getVariants(); if( !$wgDisableLangConversion && sizeof( $variants ) > 1 ) { foreach( $variants as $code ) { $varname = $wgContLang->getVariantname( $code ); if( $varname == 'disable' ) continue; $s = $wgLang->pipeList( array( $s, '' . htmlspecialchars( $varname ) . '' ) ); } } return $s; } function bottomLinks() { global $wgOut, $wgUser, $wgUseTrackbacks; $sep = wfMsgExt( 'pipe-separator', 'escapenoentities' ) . "\n"; $s = ''; if ( $wgOut->isArticleRelated() ) { $element[] = '' . $this->editThisPage() . ''; if ( $wgUser->isLoggedIn() ) { $element[] = $this->watchThisPage(); } $element[] = $this->talkLink(); $element[] = $this->historyLink(); $element[] = $this->whatLinksHere(); $element[] = $this->watchPageLinksLink(); if( $wgUseTrackbacks ) $element[] = $this->trackbackLink(); if ( $this->mTitle->getNamespace() == NS_USER || $this->mTitle->getNamespace() == NS_USER_TALK ){ $id = User::idFromName( $this->mTitle->getText() ); $ip = User::isIP( $this->mTitle->getText() ); if( $id || $ip ) { # both anons and non-anons have contri list $element[] = $this->userContribsLink(); } if( $this->showEmailUser( $id ) ) { $element[] = $this->emailUserLink(); } } $s = implode( $element, $sep ); if ( $this->mTitle->getArticleId() ) { $s .= "\n
"; if( $wgUser->isAllowed( 'delete' ) ) { $s .= $this->deleteThisPage(); } if( $wgUser->isAllowed( 'protect' ) ) { $s .= $sep . $this->protectThisPage(); } if( $wgUser->isAllowed( 'move' ) ) { $s .= $sep . $this->moveThisPage(); } } $s .= "
\n" . $this->otherLanguages(); } return $s; } function pageStats() { global $wgOut, $wgLang, $wgArticle, $wgRequest, $wgUser; global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax, $wgPageShowWatchingUsers; $oldid = $wgRequest->getVal( 'oldid' ); $diff = $wgRequest->getVal( 'diff' ); if ( ! $wgOut->isArticle() ) { return ''; } if( !$wgArticle instanceOf Article ) { return ''; } if ( isset( $oldid ) || isset( $diff ) ) { return ''; } if ( 0 == $wgArticle->getID() ) { return ''; } $s = ''; if ( !$wgDisableCounters ) { $count = $wgLang->formatNum( $wgArticle->getCount() ); if ( $count ) { $s = wfMsgExt( 'viewcount', array( 'parseinline' ), $count ); } } if( $wgMaxCredits != 0 ){ $s .= ' ' . Credits::getCredits( $wgArticle, $wgMaxCredits, $wgShowCreditsIfMax ); } else { $s .= $this->lastModified(); } if( $wgPageShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' ) ) { $dbr = wfGetDB( DB_SLAVE ); $res = $dbr->select( 'watchlist', array( 'COUNT(*) AS n' ), array( 'wl_title' => $dbr->strencode( $this->mTitle->getDBkey() ), 'wl_namespace' => $this->mTitle->getNamespace() ), __METHOD__ ); $x = $dbr->fetchObject( $res ); $s .= ' ' . wfMsgExt( 'number_of_watching_users_pageview', array( 'parseinline' ), $wgLang->formatNum( $x->n ) ); } return $s . ' ' . $this->getCopyright(); } function getCopyright( $type = 'detect' ) { global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest, $wgArticle; if ( $type == 'detect' ) { $diff = $wgRequest->getVal( 'diff' ); $isCur = $wgArticle && $wgArticle->isCurrent(); if ( is_null( $diff ) && !$isCur && wfMsgForContent( 'history_copyright' ) !== '-' ) { $type = 'history'; } else { $type = 'normal'; } } if ( $type == 'history' ) { $msg = 'history_copyright'; } else { $msg = 'copyright'; } $out = ''; if( $wgRightsPage ) { $title = Title::newFromText( $wgRightsPage ); $link = $this->linkKnown( $title, $wgRightsText ); } elseif( $wgRightsUrl ) { $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText ); } elseif( $wgRightsText ) { $link = $wgRightsText; } else { # Give up now return $out; } // Allow for site and per-namespace customization of copyright notice. if( isset($wgArticle) ) wfRunHooks( 'SkinCopyrightFooter', array( $wgArticle->getTitle(), $type, &$msg, &$link ) ); $out .= wfMsgForContent( $msg, $link ); return $out; } function getCopyrightIcon() { global $wgRightsUrl, $wgRightsText, $wgRightsIcon, $wgCopyrightIcon; $out = ''; if ( isset( $wgCopyrightIcon ) && $wgCopyrightIcon ) { $out = $wgCopyrightIcon; } else if ( $wgRightsIcon ) { $icon = htmlspecialchars( $wgRightsIcon ); if ( $wgRightsUrl ) { $url = htmlspecialchars( $wgRightsUrl ); $out .= ''; } $text = htmlspecialchars( $wgRightsText ); $out .= "$text"; if ( $wgRightsUrl ) { $out .= ''; } } return $out; } function getPoweredBy() { global $wgStylePath; $url = htmlspecialchars( "$wgStylePath/common/images/poweredby_mediawiki_88x31.png" ); $img = 'Powered by MediaWiki'; return $img; } function lastModified() { global $wgLang, $wgArticle; if( $this->mRevisionId ) { $timestamp = Revision::getTimestampFromId( $wgArticle->getTitle(), $this->mRevisionId ); } else { $timestamp = $wgArticle->getTimestamp(); } if ( $timestamp ) { $d = $wgLang->date( $timestamp, true ); $t = $wgLang->time( $timestamp, true ); $s = ' ' . wfMsg( 'lastmodifiedat', $d, $t ); } else { $s = ''; } if ( wfGetLB()->getLaggedSlaveMode() ) { $s .= ' ' . wfMsg( 'laggedslavemode' ) . ''; } return $s; } function logoText( $align = '' ) { if ( '' != $align ) { $a = " align='{$align}'"; } else { $a = ''; } $mp = wfMsg( 'mainpage' ); $mptitle = Title::newMainPage(); $url = ( is_object( $mptitle ) ? $mptitle->escapeLocalURL() : '' ); $logourl = $this->getLogo(); $s = ""; return $s; } /** * show a drop-down box of special pages */ function specialPagesList() { global $wgUser, $wgContLang, $wgServer, $wgRedirectScript; $pages = array_merge( SpecialPage::getRegularPages(), SpecialPage::getRestrictedPages() ); foreach ( $pages as $name => $page ) { $pages[$name] = $page->getDescription(); } $go = wfMsg( 'go' ); $sp = wfMsg( 'specialpages' ); $spp = $wgContLang->specialPage( 'Specialpages' ); $s = '
\n"; $s .= "\n"; $s .= "\n"; $s .= "
\n"; return $s; } function mainPageLink() { $s = $this->link( Title::newMainPage(), wfMsg( 'mainpage' ), array(), array(), array( 'known', 'noclasses' ) ); return $s; } function copyrightLink() { $title = Title::newFromText( wfMsgForContent( 'copyrightpage' ) ); $s = $this->linkKnown( $title, wfMsg( 'copyrightpagename' ) ); return $s; } private function footerLink ( $desc, $page ) { // if the link description has been set to "-" in the default language, if ( wfMsgForContent( $desc ) == '-') { // then it is disabled, for all languages. return ''; } else { // Otherwise, we display the link for the user, described in their // language (which may or may not be the same as the default language), // but we make the link target be the one site-wide page. $title = Title::newFromText( wfMsgForContent( $page ) ); return $this->linkKnown( $title, wfMsgExt( $desc, array( 'parsemag', 'escapenoentities' ) ) ); } } function privacyLink() { return $this->footerLink( 'privacy', 'privacypage' ); } function aboutLink() { return $this->footerLink( 'aboutsite', 'aboutpage' ); } function disclaimerLink() { return $this->footerLink( 'disclaimers', 'disclaimerpage' ); } function editThisPage() { global $wgOut; if ( !$wgOut->isArticleRelated() ) { $s = wfMsg( 'protectedpage' ); } else { if( $this->mTitle->quickUserCan( 'edit' ) && $this->mTitle->exists() ) { $t = wfMsg( 'editthispage' ); } elseif( $this->mTitle->quickUserCan( 'create' ) && !$this->mTitle->exists() ) { $t = wfMsg( 'create-this-page' ); } else { $t = wfMsg( 'viewsource' ); } $s = $this->link( $this->mTitle, $t, array(), $this->editUrlOptions(), array( 'known', 'noclasses' ) ); } return $s; } /** * Return URL options for the 'edit page' link. * This may include an 'oldid' specifier, if the current page view is such. * * @return array * @private */ function editUrlOptions() { global $wgArticle; $options = array( 'action' => 'edit' ); if( $this->mRevisionId && ! $wgArticle->isCurrent() ) { $options['oldid'] = intval( $this->mRevisionId ); } return $options; } function deleteThisPage() { global $wgUser, $wgRequest; $diff = $wgRequest->getVal( 'diff' ); if ( $this->mTitle->getArticleId() && ( !$diff ) && $wgUser->isAllowed( 'delete' ) ) { $t = wfMsg( 'deletethispage' ); $s = $this->link( $this->mTitle, $t, array(), array( 'action' => 'delete' ), array( 'known', 'noclasses' ) ); } else { $s = ''; } return $s; } function protectThisPage() { global $wgUser, $wgRequest; $diff = $wgRequest->getVal( 'diff' ); if ( $this->mTitle->getArticleId() && ( ! $diff ) && $wgUser->isAllowed('protect') ) { if ( $this->mTitle->isProtected() ) { $text = wfMsg( 'unprotectthispage' ); $query = array( 'action' => 'unprotect' ); } else { $text = wfMsg( 'protectthispage' ); $query = array( 'action' => 'protect' ); } $s = $this->link( $this->mTitle, $text, array(), $query, array( 'known', 'noclasses' ) ); } else { $s = ''; } return $s; } function watchThisPage() { global $wgOut; ++$this->mWatchLinkNum; if ( $wgOut->isArticleRelated() ) { if ( $this->mTitle->userIsWatching() ) { $text = wfMsg( 'unwatchthispage' ); $query = array( 'action' => 'unwatch' ); $id = 'mw-unwatch-link' . $this->mWatchLinkNum; } else { $text = wfMsg( 'watchthispage' ); $query = array( 'action' => 'watch' ); $id = 'mw-watch-link' . $this->mWatchLinkNum; } $s = $this->link( $this->mTitle, $text, array( 'id' => $id ), $query, array( 'known', 'noclasses' ) ); } else { $s = wfMsg( 'notanarticle' ); } return $s; } function moveThisPage() { if ( $this->mTitle->quickUserCan( 'move' ) ) { return $this->link( SpecialPage::getTitleFor( 'Movepage' ), wfMsg( 'movethispage' ), array(), array( 'target' => $this->mTitle->getPrefixedURL() ), array( 'known', 'noclasses' ) ); } else { // no message if page is protected - would be redundant return ''; } } function historyLink() { return $this->link( $this->mTitle, wfMsgHtml( 'history' ), array( 'rel' => 'archives' ), array( 'action' => 'history' ) ); } function whatLinksHere() { return $this->link( SpecialPage::getTitleFor( 'Whatlinkshere', $this->mTitle->getPrefixedDBkey() ), wfMsgHtml( 'whatlinkshere' ), array(), array(), array( 'known', 'noclasses' ) ); } function userContribsLink() { return $this->link( SpecialPage::getTitleFor( 'Contributions', $this->mTitle->getDBkey() ), wfMsgHtml( 'contributions' ), array(), array(), array( 'known', 'noclasses' ) ); } function showEmailUser( $id ) { global $wgUser; $targetUser = User::newFromId( $id ); return $wgUser->canSendEmail() && # the sending user must have a confirmed email address $targetUser->canReceiveEmail(); # the target user must have a confirmed email address and allow emails from users } function emailUserLink() { return $this->link( SpecialPage::getTitleFor( 'Emailuser', $this->mTitle->getDBkey() ), wfMsg( 'emailuser' ), array(), array(), array( 'known', 'noclasses' ) ); } function watchPageLinksLink() { global $wgOut; if ( ! $wgOut->isArticleRelated() ) { return '(' . wfMsg( 'notanarticle' ) . ')'; } else { return $this->link( SpecialPage::getTitleFor( 'Recentchangeslinked', $this->mTitle->getPrefixedDBkey() ), wfMsg( 'recentchangeslinked-toolbox' ), array(), array(), array( 'known', 'noclasses' ) ); } } function trackbackLink() { return '' . wfMsg( 'trackbacklink' ) . ''; } function otherLanguages() { global $wgOut, $wgContLang, $wgHideInterlanguageLinks; if ( $wgHideInterlanguageLinks ) { return ''; } $a = $wgOut->getLanguageLinks(); if ( 0 == count( $a ) ) { return ''; } $s = wfMsg( 'otherlanguages' ) . wfMsg( 'colon-separator' ); $first = true; if( $wgContLang->isRTL() ) $s .= ''; foreach( $a as $l ) { if ( !$first ) { $s .= wfMsgExt( 'pipe-separator', 'escapenoentities' ); } $first = false; $nt = Title::newFromText( $l ); $url = $nt->escapeFullURL(); $text = $wgContLang->getLanguageName( $nt->getInterwiki() ); if ( '' == $text ) { $text = $l; } $style = $this->getExternalLinkAttributes(); $s .= "{$text}"; } if( $wgContLang->isRTL() ) $s .= ''; return $s; } function talkLink() { if ( NS_SPECIAL == $this->mTitle->getNamespace() ) { # No discussion links for special pages return ''; } $linkOptions = array(); if( $this->mTitle->isTalkPage() ) { $link = $this->mTitle->getSubjectPage(); switch( $link->getNamespace() ) { case NS_MAIN: $text = wfMsg( 'articlepage' ); break; case NS_USER: $text = wfMsg( 'userpage' ); break; case NS_PROJECT: $text = wfMsg( 'projectpage' ); break; case NS_FILE: $text = wfMsg( 'imagepage' ); # Make link known if image exists, even if the desc. page doesn't. if( wfFindFile( $link ) ) $linkOptions[] = 'known'; break; case NS_MEDIAWIKI: $text = wfMsg( 'mediawikipage' ); break; case NS_TEMPLATE: $text = wfMsg( 'templatepage' ); break; case NS_HELP: $text = wfMsg( 'viewhelppage' ); break; case NS_CATEGORY: $text = wfMsg( 'categorypage' ); break; default: $text = wfMsg( 'articlepage' ); } } else { $link = $this->mTitle->getTalkPage(); $text = wfMsg( 'talkpage' ); } $s = $this->link( $link, $text, array(), array(), $linkOptions ); return $s; } function commentLink() { global $wgOut; if ( $this->mTitle->getNamespace() == NS_SPECIAL ) { return ''; } # __NEWSECTIONLINK___ changes behaviour here # If it is present, the link points to this page, otherwise # it points to the talk page if( $this->mTitle->isTalkPage() ) { $title = $this->mTitle; } elseif( $wgOut->showNewSectionLink() ) { $title = $this->mTitle; } else { $title = $this->mTitle->getTalkPage(); } return $this->link( $title, wfMsg( 'postcomment' ), array(), array( 'action' => 'edit', 'section' => 'new' ), array( 'known', 'noclasses' ) ); } /* these are used extensively in SkinTemplate, but also some other places */ static function makeMainPageUrl( $urlaction = '' ) { $title = Title::newMainPage(); self::checkTitle( $title, '' ); return $title->getLocalURL( $urlaction ); } static function makeSpecialUrl( $name, $urlaction = '' ) { $title = SpecialPage::getTitleFor( $name ); return $title->getLocalURL( $urlaction ); } static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) { $title = SpecialPage::getSafeTitleFor( $name, $subpage ); return $title->getLocalURL( $urlaction ); } static function makeI18nUrl( $name, $urlaction = '' ) { $title = Title::newFromText( wfMsgForContent( $name ) ); self::checkTitle( $title, $name ); return $title->getLocalURL( $urlaction ); } static function makeUrl( $name, $urlaction = '' ) { $title = Title::newFromText( $name ); self::checkTitle( $title, $name ); return $title->getLocalURL( $urlaction ); } # If url string starts with http, consider as external URL, else # internal static function makeInternalOrExternalUrl( $name ) { if ( preg_match( '/^(?:' . wfUrlProtocols() . ')/', $name ) ) { return $name; } else { return self::makeUrl( $name ); } } # this can be passed the NS number as defined in Language.php static function makeNSUrl( $name, $urlaction = '', $namespace = NS_MAIN ) { $title = Title::makeTitleSafe( $namespace, $name ); self::checkTitle( $title, $name ); return $title->getLocalURL( $urlaction ); } /* these return an array with the 'href' and boolean 'exists' */ static function makeUrlDetails( $name, $urlaction = '' ) { $title = Title::newFromText( $name ); self::checkTitle( $title, $name ); return array( 'href' => $title->getLocalURL( $urlaction ), 'exists' => $title->getArticleID() != 0 ? true : false ); } /** * Make URL details where the article exists (or at least it's convenient to think so) */ static function makeKnownUrlDetails( $name, $urlaction = '' ) { $title = Title::newFromText( $name ); self::checkTitle( $title, $name ); return array( 'href' => $title->getLocalURL( $urlaction ), 'exists' => true ); } # make sure we have some title to operate on static function checkTitle( &$title, $name ) { if( !is_object( $title ) ) { $title = Title::newFromText( $name ); if( !is_object( $title ) ) { $title = Title::newFromText( '--error: link target missing--' ); } } } /** * Build an array that represents the sidebar(s), the navigation bar among them * * @return array */ function buildSidebar() { global $parserMemc, $wgEnableSidebarCache, $wgSidebarCacheExpiry; global $wgLang; wfProfileIn( __METHOD__ ); $key = wfMemcKey( 'sidebar', $wgLang->getCode() ); if ( $wgEnableSidebarCache ) { $cachedsidebar = $parserMemc->get( $key ); if ( $cachedsidebar ) { wfProfileOut( __METHOD__ ); return $cachedsidebar; } } $bar = array(); $lines = explode( "\n", wfMsgForContent( 'sidebar' ) ); $heading = ''; foreach( $lines as $line ) { if( strpos( $line, '*' ) !== 0 ) continue; if( strpos( $line, '**') !== 0 ) { $heading = trim( $line, '* ' ); if( !array_key_exists( $heading, $bar ) ) $bar[$heading] = array(); } else { if( strpos( $line, '|' ) !== false ) { // sanity check $line = array_map( 'trim', explode( '|', trim( $line, '* ' ), 2 ) ); $link = wfMsgForContent( $line[0] ); if( $link == '-' ) continue; $text = wfMsgExt( $line[1], 'parsemag' ); if( wfEmptyMsg( $line[1], $text ) ) $text = $line[1]; if( wfEmptyMsg( $line[0], $link ) ) $link = $line[0]; if ( preg_match( '/^(?:' . wfUrlProtocols() . ')/', $link ) ) { $href = $link; } else { $title = Title::newFromText( $link ); if ( $title ) { $title = $title->fixSpecialName(); $href = $title->getLocalURL(); } else { $href = 'INVALID-TITLE'; } } $bar[$heading][] = array( 'text' => $text, 'href' => $href, 'id' => 'n-' . strtr( $line[1], ' ', '-' ), 'active' => false ); } else { continue; } } } wfRunHooks( 'SkinBuildSidebar', array( $this, &$bar ) ); if ( $wgEnableSidebarCache ) $parserMemc->set( $key, $bar, $wgSidebarCacheExpiry ); wfProfileOut( __METHOD__ ); return $bar; } /** * Should we include common/wikiprintable.css? Skins that have their own * print stylesheet should override this and return false. (This is an * ugly hack to get Monobook to play nicely with * OutputPage::headElement().) * * @return bool */ public function commonPrintStylesheet() { return true; } }