diff options
Diffstat (limited to 'includes/Skin.php')
-rw-r--r-- | includes/Skin.php | 288 |
1 files changed, 191 insertions, 97 deletions
diff --git a/includes/Skin.php b/includes/Skin.php index ffbe27c7..3e4f5d3c 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -23,6 +23,7 @@ class Skin extends Linker { var $rc_cache ; # Cache for Enhanced Recent Changes var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle var $rcMoveIndex; + var $mWatchLinkNum = 0; // Appended to end of watch link id's /**#@-*/ /** Constructor, call parent constructor */ @@ -48,6 +49,7 @@ class Skin extends Linker { # while code from www.php.net while (false !== ($file = $skinDir->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; @@ -116,10 +118,9 @@ class Skin extends Linker { $skinName = $skinNames[$key]; # Grab the skin class and initialise it. - wfSuppressWarnings(); // Preload base classes to work around APC/PHP5 bug - include_once( "{$wgStyleDirectory}/{$skinName}.deps.php" ); - wfRestoreWarnings(); + $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 @@ -139,7 +140,7 @@ class Skin extends Linker { /** @return string path to the skin stylesheet */ function getStylesheet() { - return 'common/wikistandard.css?1'; + return 'common/wikistandard.css'; } /** @return string skin name */ @@ -151,8 +152,7 @@ class Skin extends Linker { global $wgOut, $wgUser; if ( $wgOut->isQuickbarSuppressed() ) { return 0; } - $q = $wgUser->getOption( 'quickbar' ); - if ( '' == $q ) { $q = 0; } + $q = $wgUser->getOption( 'quickbar', 0 ); return $q; } @@ -270,60 +270,71 @@ class Skin extends Linker { $out->out( "\n</body></html>" ); } - static function makeGlobalVariablesScript( $data ) { - $r = '<script type= "' . $data['jsmimetype'] . '"> - var skin = "' . Xml::escapeJsString( $data['skinname'] ) . '"; - var stylepath = "' . Xml::escapeJsString( $data['stylepath'] ) . '"; - - var wgArticlePath = "' . Xml::escapeJsString( $data['articlepath'] ) . '"; - var wgScriptPath = "' . Xml::escapeJsString( $data['scriptpath'] ) . '"; - var wgServer = "' . Xml::escapeJsString( $data['serverurl'] ) . '"; - - var wgCanonicalNamespace = "' . Xml::escapeJsString( $data['nscanonical'] ) . '"; - var wgNamespaceNumber = ' . (int)$data['nsnumber'] . '; - var wgPageName = "' . Xml::escapeJsString( $data['titleprefixeddbkey'] ) . '"; - var wgTitle = "' . Xml::escapeJsString( $data['titletext'] ) . '"; - var wgArticleId = ' . (int)$data['articleid'] . '; - var wgIsArticle = ' . ( $data['isarticle'] ? 'true' : 'false' ) . '; - - var wgUserName = ' . ( $data['username'] == NULL ? 'null' : ( '"' . Xml::escapeJsString( $data['username'] ) . '"' ) ) . '; - var wgUserLanguage = "' . Xml::escapeJsString( $data['userlang'] ) . '"; - var wgContentLanguage = "' . Xml::escapeJsString( $data['lang'] ) . '"; - </script> - '; - + static function makeVariablesScript( $data ) { + global $wgJsMimeType; + + $r = "<script type= \"$wgJsMimeType\">/*<![CDATA[*/\n"; + foreach ( $data as $name => $value ) { + $encValue = Xml::encodeJsVar( $value ); + $r .= "var $name = $encValue;\n"; + } + $r .= "/*]]>*/</script>\n"; + return $r; } - function getHeadScripts() { - global $wgStylePath, $wgUser, $wgAllowUserJs, $wgJsMimeType; + /** + * Make a <script> tag containing global variables + * @param array $data Associative array containing one element: + * skinname => the skin name + * The odd calling convention is for backwards compatibility + */ + static function makeGlobalVariablesScript( $data ) { + global $wgStylePath, $wgUser; global $wgArticlePath, $wgScriptPath, $wgServer, $wgContLang, $wgLang; - global $wgTitle, $wgCanonicalNamespaceNames, $wgOut; - - $nsname = @$wgCanonicalNamespaceNames[ $wgTitle->getNamespace() ]; - if ( $nsname === NULL ) $nsname = $wgTitle->getNsText(); + global $wgTitle, $wgCanonicalNamespaceNames, $wgOut, $wgArticle; + global $wgBreakFrames; + $ns = $wgTitle->getNamespace(); + $nsname = isset( $wgCanonicalNamespaceNames[ $ns ] ) ? $wgCanonicalNamespaceNames[ $ns ] : $wgTitle->getNsText(); + $vars = array( - 'jsmimetype' => $wgJsMimeType, - 'skinname' => $this->getSkinName(), + 'skin' => $data['skinname'], 'stylepath' => $wgStylePath, - 'articlepath' => $wgArticlePath, - 'scriptpath' => $wgScriptPath, - 'serverurl' => $wgServer, - 'nscanonical' => $nsname, - 'nsnumber' => $wgTitle->getNamespace(), - 'titleprefixeddbkey' => $wgTitle->getPrefixedDBKey(), - 'titletext' => $wgTitle->getText(), - 'articleid' => $wgTitle->getArticleId(), - 'isarticle' => $wgOut->isArticle(), - 'username' => $wgUser->isAnon() ? NULL : $wgUser->getName(), - 'userlang' => $wgLang->getCode(), - 'lang' => $wgContLang->getCode(), + 'wgArticlePath' => $wgArticlePath, + 'wgScriptPath' => $wgScriptPath, + 'wgServer' => $wgServer, + 'wgCanonicalNamespace' => $nsname, + 'wgCanonicalSpecialPageName' => SpecialPage::resolveAlias( $wgTitle->getDBKey() ), + 'wgNamespaceNumber' => $wgTitle->getNamespace(), + 'wgPageName' => $wgTitle->getPrefixedDBKey(), + 'wgTitle' => $wgTitle->getText(), + 'wgArticleId' => $wgTitle->getArticleId(), + 'wgIsArticle' => $wgOut->isArticle(), + 'wgUserName' => $wgUser->isAnon() ? NULL : $wgUser->getName(), + 'wgUserLanguage' => $wgLang->getCode(), + 'wgContentLanguage' => $wgContLang->getCode(), + 'wgBreakFrames' => $wgBreakFrames, + 'wgCurRevisionId' => isset( $wgArticle ) ? $wgArticle->getLatest() : 0, ); - $r = self::makeGlobalVariablesScript( $vars ); + return self::makeVariablesScript( $vars ); + } + + function getHeadScripts() { + global $wgStylePath, $wgUser, $wgAllowUserJs, $wgJsMimeType, $wgStyleVersion; + + $r = self::makeGlobalVariablesScript( array( 'skinname' => $this->getSkinName() ) ); - $r .= "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/wikibits.js\"></script>\n"; + $r .= "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/wikibits.js?$wgStyleVersion\"></script>\n"; + global $wgUseSiteJs; + if ($wgUseSiteJs) { + if ($wgUser->isLoggedIn()) { + $r .= "<script type=\"$wgJsMimeType\" src=\"".htmlspecialchars(self::makeUrl('-','action=raw&smaxage=0&gen=js'))."\"><!-- site js --></script>\n"; + } else { + $r .= "<script type=\"$wgJsMimeType\" src=\"".htmlspecialchars(self::makeUrl('-','action=raw&gen=js'))."\"><!-- site js --></script>\n"; + } + } if( $wgAllowUserJs && $wgUser->isLoggedIn() ) { $userpage = $wgUser->getUserPage(); $userjs = htmlspecialchars( self::makeUrl( @@ -360,11 +371,11 @@ class Skin extends Linker { # get the user/site-specific stylesheet, SkinTemplate loads via RawPage.php (settings are cached that way) function getUserStylesheet() { - global $wgStylePath, $wgRequest, $wgContLang, $wgSquidMaxage; + global $wgStylePath, $wgRequest, $wgContLang, $wgSquidMaxage, $wgStyleVersion; $sheet = $this->getStylesheet(); - $action = $wgRequest->getText('action'); - $s = "@import \"$wgStylePath/$sheet\";\n"; - if($wgContLang->isRTL()) $s .= "@import \"$wgStylePath/common/common_rtl.css\";\n"; + $s = "@import \"$wgStylePath/common/common.css?$wgStyleVersion\";\n"; + $s .= "@import \"$wgStylePath/$sheet?$wgStyleVersion\";\n"; + if($wgContLang->isRTL()) $s .= "@import \"$wgStylePath/common/common_rtl.css?$wgStyleVersion\";\n"; $query = "usemsgcache=yes&action=raw&ctype=text/css&smaxage=$wgSquidMaxage"; $s .= '@import "' . self::makeNSUrl( 'Common.css', $query, NS_MEDIAWIKI ) . "\";\n" . @@ -375,9 +386,40 @@ class Skin extends Linker { } /** - * placeholder, returns generated js in monobook + * This returns MediaWiki:Common.js. For some bizarre reason, it does + * *not* return any custom user JS from user subpages. Huh? + * + * @return string */ - function getUserJs() { return; } + function getUserJs() { + $fname = 'Skin::getUserJs'; + wfProfileIn( __METHOD__ ); + + global $wgStylePath; + $s = "/* generated javascript */\n"; + $s .= "var skin = '{$this->skinname}';\nvar stylepath = '{$wgStylePath}';"; + $s .= "\n\n/* MediaWiki:Common.js */\n"; + $commonJs = wfMsgForContent('common.js'); + if ( !wfEmptyMsg ( 'common.js', $commonJs ) ) { + $s .= $commonJs; + } + + global $wgUseAjax, $wgAjaxWatch; + if($wgUseAjax && $wgAjaxWatch) { + $s .= " + +/* AJAX (un)watch (see /skins/common/ajaxwatch.js) */ +var wgAjaxWatch = { + watchMsg: '". str_replace( array("'", "\n"), array("\\'", ' '), wfMsgExt( 'watch', array() ) )."', + unwatchMsg: '". str_replace( array("'", "\n"), array("\\'", ' '), wfMsgExt( 'unwatch', array() ) )."', + watchingMsg: '". str_replace( array("'", "\n"), array("\\'", ' '), wfMsgExt( 'watching', array() ) )."', + unwatchingMsg: '". str_replace( array("'", "\n"), array("\\'", ' '), wfMsgExt( 'unwatching', array() ) )."' +};"; + } + + wfProfileOut( __METHOD__ ); + return $s; + } /** * Return html code that include User stylesheets @@ -464,7 +506,6 @@ END; else $a = array( 'bgcolor' => '#FFFFFF' ); if($wgOut->isArticle() && $wgUser->getOption('editondblclick') && $wgTitle->userCanEdit() ) { - $t = wfMsg( 'editthispage' ); $s = $wgTitle->getFullURL( $this->editUrlOptions() ); $s = 'document.location = "' .wfEscapeJSString( $s ) .'";'; $a += array ('ondblclick' => $s); @@ -477,7 +518,8 @@ END; } $a['onload'] .= 'setupRightClickEdit()'; } - $a['class'] = 'ns-'.$wgTitle->getNamespace().' '.($wgContLang->isRTL() ? "rtl" : "ltr"); + $a['class'] = 'ns-'.$wgTitle->getNamespace().' '.($wgContLang->isRTL() ? "rtl" : "ltr"). + ' '.Sanitizer::escapeId( 'page-'.$wgTitle->getPrefixedText() ); return $a; } @@ -576,9 +618,8 @@ END; $pop = '</span>'; $t = $embed . implode ( "{$pop} {$sep} {$embed}" , $wgOut->mCategoryLinks ) . $pop; - $msg = wfMsgExt('categories', array('parsemag', 'escape'), count( $wgOut->mCategoryLinks )); - $s = $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Categories' ), - $msg, 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) ) + $msg = wfMsgExt( 'pagecategories', array( 'parsemag', 'escape' ), count( $wgOut->mCategoryLinks ) ); + $s = $this->makeLinkObj( Title::newFromText( wfMsgForContent('pagecategorieslink') ), $msg ) . ': ' . $t; # optional 'dmoz-like' category browser. Will be shown under the list @@ -670,7 +711,8 @@ END; function pageTitleLinks() { global $wgOut, $wgTitle, $wgUser, $wgRequest; - extract( $wgRequest->getValues( 'oldid', 'diff' ) ); + $oldid = $wgRequest->getVal( 'oldid' ); + $diff = $wgRequest->getVal( 'diff' ); $action = $wgRequest->getText( 'action' ); $s = $this->printableLink(); @@ -731,8 +773,8 @@ END; $msg = 'viewdeleted'; } return wfMsg( $msg, - $this->makeKnownLink( - $wgContLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ), + $this->makeKnownLinkObj( + SpecialPage::getTitleFor( 'Undelete', $wgTitle->getPrefixedDBkey() ), wfMsgExt( 'restorelink', array( 'parsemag', 'escape' ), $n ) ) ); } return ''; @@ -812,7 +854,6 @@ END; function nameAndLogin() { global $wgUser, $wgTitle, $wgLang, $wgContLang, $wgShowIPinHeader; - $li = $wgContLang->specialPage( 'Userlogin' ); $lo = $wgContLang->specialPage( 'Userlogout' ); $s = ''; @@ -834,7 +875,7 @@ END; } else { $q = "returnto={$rt}"; } $s .= "\n<br />" . $this->makeKnownLinkObj( - Title::makeTitle( NS_SPECIAL, 'Userlogin' ), + SpecialPage::getTitleFor( 'Userlogin' ), wfMsg( 'login' ), $q ); } else { $n = $wgUser->getName(); @@ -846,7 +887,7 @@ END; $s .= $this->makeKnownLinkObj( $wgUser->getUserPage(), $n ) . "{$tl}<br />" . - $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Userlogout' ), wfMsg( 'logout' ), + $this->makeKnownLinkObj( SpecialPage::getTitleFor( 'Userlogout' ), wfMsg( 'logout' ), "returnto={$rt}" ) . ' | ' . $this->specialLink( 'preferences' ); } @@ -857,7 +898,7 @@ END; } function getSearchLink() { - $searchPage =& Title::makeTitle( NS_SPECIAL, 'Search' ); + $searchPage = SpecialPage::getTitleFor( 'Search' ); return $searchPage->getLocalURL(); } @@ -892,7 +933,38 @@ END; } # Many people don't like this dropdown box #$s .= $sep . $this->specialPagesList(); + + $s .= $this->variantLinks(); + + $s .= $this->extensionTabLinks(); + return $s; + } + + /** + * 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(); + $s = ''; + wfRunHooks( 'SkinTemplateTabs', array( $this, &$tabs ) ); + foreach( $tabs as $tab ) { + $s .= ' | ' . Xml::element( 'a', + array( 'href' => $tab['href'] ), + $tab['text'] ); + } + return $s; + } + + /** + * Language/charset variant links for classic-style skins + * @return string + */ + function variantLinks() { + $s = ''; /* show links to different language variants */ global $wgDisableLangConversion, $wgContLang, $wgTitle; $variants = $wgContLang->getVariants(); @@ -901,10 +973,9 @@ END; $varname = $wgContLang->getVariantname( $code ); if( $varname == 'disable' ) continue; - $s .= ' | <a href="' . $wgTitle->getLocalUrl( 'variant=' . $code ) . '">' . $varname . '</a>'; + $s .= ' | <a href="' . $wgTitle->escapeLocalUrl( 'variant=' . $code ) . '">' . htmlspecialchars( $varname ) . '</a>'; } } - return $s; } @@ -955,7 +1026,8 @@ END; global $wgOut, $wgLang, $wgArticle, $wgRequest, $wgUser; global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax, $wgTitle, $wgPageShowWatchingUsers; - extract( $wgRequest->getValues( 'oldid', 'diff' ) ); + $oldid = $wgRequest->getVal( 'oldid' ); + $diff = $wgRequest->getVal( 'diff' ); if ( ! $wgOut->isArticle() ) { return ''; } if ( isset( $oldid ) || isset( $diff ) ) { return ''; } if ( 0 == $wgArticle->getID() ) { return ''; } @@ -977,7 +1049,7 @@ END; if ($wgPageShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' )) { $dbr =& wfGetDB( DB_SLAVE ); - extract( $dbr->tableNames( 'watchlist' ) ); + $watchlist = $dbr->tableName( 'watchlist' ); $sql = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_title='" . $dbr->strencode($wgTitle->getDBKey()) . "' AND wl_namespace=" . $wgTitle->getNamespace() ; @@ -1045,7 +1117,7 @@ END; function getPoweredBy() { global $wgStylePath; $url = htmlspecialchars( "$wgStylePath/common/images/poweredby_mediawiki_88x31.png" ); - $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>'; + $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="Powered by MediaWiki" /></a>'; return $img; } @@ -1071,12 +1143,8 @@ END; else { $a = ''; } $mp = wfMsg( 'mainpage' ); - $titleObj = Title::newFromText( $mp ); - if ( is_object( $titleObj ) ) { - $url = $titleObj->escapeLocalURL(); - } else { - $url = ''; - } + $mptitle = Title::newMainPage(); + $url = ( is_object($mptitle) ? $mptitle->escapeLocalURL() : '' ); $logourl = $this->getLogo(); $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>"; @@ -1088,7 +1156,6 @@ END; */ function specialPagesList() { global $wgUser, $wgContLang, $wgServer, $wgRedirectScript; - $a = array(); $pages = array_merge( SpecialPage::getRegularPages(), SpecialPage::getRestrictedPages() ); foreach ( $pages as $name => $page ) { $pages[$name] = $page->getDescription(); @@ -1115,9 +1182,7 @@ END; } function mainPageLink() { - $mp = wfMsgForContent( 'mainpage' ); - $mptxt = wfMsg( 'mainpage'); - $s = $this->makeKnownLink( $mp, $mptxt ); + $s = $this->makeKnownLinkObj( Title::newMainPage(), wfMsg( 'mainpage' ) ); return $s; } @@ -1221,16 +1286,19 @@ END; function watchThisPage() { global $wgOut, $wgTitle; + ++$this->mWatchLinkNum; if ( $wgOut->isArticleRelated() ) { if ( $wgTitle->userIsWatching() ) { $t = wfMsg( 'unwatchthispage' ); $q = 'action=unwatch'; + $id = "mw-unwatch-link".$this->mWatchLinkNum; } else { $t = wfMsg( 'watchthispage' ); $q = 'action=watch'; + $id = 'mw-watch-link'.$this->mWatchLinkNum; } - $s = $this->makeKnownLinkObj( $wgTitle, $t, $q ); + $s = $this->makeKnownLinkObj( $wgTitle, $t, $q, '', '', " id=\"$id\"" ); } else { $s = wfMsg( 'notanarticle' ); } @@ -1241,7 +1309,7 @@ END; global $wgTitle; if ( $wgTitle->userCanMove() ) { - return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Movepage' ), + return $this->makeKnownLinkObj( SpecialPage::getTitleFor( 'Movepage' ), wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() ); } else { // no message if page is protected - would be redundant @@ -1259,15 +1327,17 @@ END; function whatLinksHere() { global $wgTitle; - return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Whatlinkshere' ), - wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() ); + return $this->makeKnownLinkObj( + SpecialPage::getTitleFor( 'Whatlinkshere', $wgTitle->getPrefixedDBkey() ), + wfMsg( 'whatlinkshere' ) ); } function userContribsLink() { global $wgTitle; - return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), - wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() ); + return $this->makeKnownLinkObj( + SpecialPage::getTitleFor( 'Contributions', $wgTitle->getDBkey() ), + wfMsg( 'contributions' ) ); } function showEmailUser( $id ) { @@ -1284,8 +1354,9 @@ END; function emailUserLink() { global $wgTitle; - return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Emailuser' ), - wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() ); + return $this->makeKnownLinkObj( + SpecialPage::getTitleFor( 'Emailuser', $wgTitle->getDBkey() ), + wfMsg( 'emailuser' ) ); } function watchPageLinksLink() { @@ -1294,9 +1365,9 @@ END; if ( ! $wgOut->isArticleRelated() ) { return '(' . wfMsg( 'notanarticle' ) . ')'; } else { - return $this->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, - 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ), - 'target=' . $wgTitle->getPrefixedURL() ); + return $this->makeKnownLinkObj( + SpecialPage::getTitleFor( 'Recentchangeslinked', $wgTitle->getPrefixedDBkey() ), + wfMsg( 'recentchangeslinked' ) ); } } @@ -1437,8 +1508,19 @@ END; } /* these are used extensively in SkinTemplate, but also some other places */ + static function makeMainPageUrl( $urlaction = '' ) { + $title = Title::newMainPage(); + self::checkTitle( $title, $name ); + return $title->getLocalURL( $urlaction ); + } + static function makeSpecialUrl( $name, $urlaction = '' ) { - $title = Title::makeTitle( NS_SPECIAL, $name ); + $title = SpecialPage::getTitleFor( $name ); + return $title->getLocalURL( $urlaction ); + } + + static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) { + $title = SpecialPage::getSafeTitleFor( $name, $subpage ); return $title->getLocalURL( $urlaction ); } @@ -1547,7 +1629,19 @@ END; $text = $line[1]; if (wfEmptyMsg($line[0], $link)) $link = $line[0]; - $href = self::makeInternalOrExternalUrl( $link ); + + 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, @@ -1558,7 +1652,7 @@ END; } } if ($cacheSidebar) - $cachednotice = $parserMemc->set( $key, $bar, 86400 ); + $parserMemc->set( $key, $bar, 86400 ); wfProfileOut( $fname ); return $bar; } |