00001 <?php
00006 if ( ! defined( 'MEDIAWIKI' ) )
00007 die( 1 );
00008
00017 class Skin extends Linker {
00021 var $mWatchLinkNum = 0;
00022
00023 protected $searchboxes = '';
00025 protected $mRevisionId;
00026 protected $skinname = 'standard' ;
00027
00029 function Skin() { parent::__construct(); }
00030
00036 static function getSkinNames() {
00037 global $wgValidSkinNames;
00038 static $skinsInitialised = false;
00039 if ( !$skinsInitialised ) {
00040 # Get a list of available skins
00041 # Build using the regular expression '^(.*).php$'
00042 # Array keys are all lower case, array value keep the case used by filename
00043 #
00044 wfProfileIn( __METHOD__ . '-init' );
00045 global $wgStyleDirectory;
00046 $skinDir = dir( $wgStyleDirectory );
00047
00048 # while code from www.php.net
00049 while (false !== ($file = $skinDir->read())) {
00050
00051 $matches = array();
00052 if(preg_match('/^([^.]*)\.php$/',$file, $matches)) {
00053 $aSkin = $matches[1];
00054 $wgValidSkinNames[strtolower($aSkin)] = $aSkin;
00055 }
00056 }
00057 $skinDir->close();
00058 $skinsInitialised = true;
00059 wfProfileOut( __METHOD__ . '-init' );
00060 }
00061 return $wgValidSkinNames;
00062 }
00063
00070 public static function getUsableSkins() {
00071 global $wgSkipSkins;
00072 $usableSkins = self::getSkinNames();
00073 foreach ( $wgSkipSkins as $skip ) {
00074 unset( $usableSkins[$skip] );
00075 }
00076 return $usableSkins;
00077 }
00078
00087 static function normalizeKey( $key ) {
00088 global $wgDefaultSkin;
00089 $skinNames = Skin::getSkinNames();
00090
00091 if( $key == '' ) {
00092
00093
00094 $key = $wgDefaultSkin;
00095 }
00096
00097 if( isset( $skinNames[$key] ) ) {
00098 return $key;
00099 }
00100
00101
00102
00103 $fallback = array(
00104 0 => $wgDefaultSkin,
00105 1 => 'nostalgia',
00106 2 => 'cologneblue' );
00107
00108 if( isset( $fallback[$key] ) ){
00109 $key = $fallback[$key];
00110 }
00111
00112 if( isset( $skinNames[$key] ) ) {
00113 return $key;
00114 } else {
00115 return 'monobook';
00116 }
00117 }
00118
00125 static function &newFromKey( $key ) {
00126 global $wgStyleDirectory;
00127
00128 $key = Skin::normalizeKey( $key );
00129
00130 $skinNames = Skin::getSkinNames();
00131 $skinName = $skinNames[$key];
00132 $className = 'Skin'.ucfirst($key);
00133
00134 # Grab the skin class and initialise it.
00135 if ( !class_exists( $className ) ) {
00136
00137 $deps = "{$wgStyleDirectory}/{$skinName}.deps.php";
00138 if( file_exists( $deps ) ) include_once( $deps );
00139 require_once( "{$wgStyleDirectory}/{$skinName}.php" );
00140
00141 # Check if we got if not failback to default skin
00142 if( !class_exists( $className ) ) {
00143 # DO NOT die if the class isn't found. This breaks maintenance
00144 # scripts and can cause a user account to be unrecoverable
00145 # except by SQL manipulation if a previously valid skin name
00146 # is no longer valid.
00147 wfDebug( "Skin class does not exist: $className\n" );
00148 $className = 'SkinMonobook';
00149 require_once( "{$wgStyleDirectory}/MonoBook.php" );
00150 }
00151 }
00152 $skin = new $className;
00153 return $skin;
00154 }
00155
00157 function getStylesheet() {
00158 return 'common/wikistandard.css';
00159 }
00160
00162 public function getSkinName() {
00163 return $this->skinname;
00164 }
00165
00166 function qbSetting() {
00167 global $wgOut, $wgUser;
00168
00169 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
00170 $q = $wgUser->getOption( 'quickbar', 0 );
00171 return $q;
00172 }
00173
00174 function initPage( OutputPage $out ) {
00175 global $wgFavicon, $wgAppleTouchIcon;
00176
00177 wfProfileIn( __METHOD__ );
00178
00179 # Generally the order of the favicon and apple-touch-icon links
00180 # should not matter, but Konqueror (3.5.9 at least) incorrectly
00181 # uses whichever one appears later in the HTML source. Make sure
00182 # apple-touch-icon is specified first to avoid this.
00183 if( false !== $wgAppleTouchIcon ) {
00184 $out->addLink( array( 'rel' => 'apple-touch-icon', 'href' => $wgAppleTouchIcon ) );
00185 }
00186
00187 if( false !== $wgFavicon ) {
00188 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => $wgFavicon ) );
00189 }
00190
00191 # OpenSearch description link
00192 $out->addLink( array(
00193 'rel' => 'search',
00194 'type' => 'application/opensearchdescription+xml',
00195 'href' => wfScript( 'opensearch_desc' ),
00196 'title' => wfMsgForContent( 'opensearch-desc' ),
00197 ));
00198
00199 $this->addMetadataLinks($out);
00200
00201 $this->mRevisionId = $out->mRevisionId;
00202
00203 $this->preloadExistence();
00204
00205 wfProfileOut( __METHOD__ );
00206 }
00207
00211 function preloadExistence() {
00212 global $wgUser, $wgTitle;
00213
00214
00215 $titles = array( $wgUser->getUserPage(), $wgUser->getTalkPage() );
00216
00217
00218 if ( $wgTitle->getNamespace() == NS_SPECIAL ) {
00219
00220 } elseif ( $wgTitle->isTalkPage() ) {
00221 $titles[] = $wgTitle->getSubjectPage();
00222 } else {
00223 $titles[] = $wgTitle->getTalkPage();
00224 }
00225
00226 $lb = new LinkBatch( $titles );
00227 $lb->execute();
00228 }
00229
00230 function addMetadataLinks( OutputPage $out ) {
00231 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf;
00232 global $wgRightsPage, $wgRightsUrl;
00233
00234 if( $out->isArticleRelated() ) {
00235 # note: buggy CC software only reads first "meta" link
00236 if( $wgEnableCreativeCommonsRdf ) {
00237 $out->addMetadataLink( array(
00238 'title' => 'Creative Commons',
00239 'type' => 'application/rdf+xml',
00240 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
00241 }
00242 if( $wgEnableDublinCoreRdf ) {
00243 $out->addMetadataLink( array(
00244 'title' => 'Dublin Core',
00245 'type' => 'application/rdf+xml',
00246 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
00247 }
00248 }
00249 $copyright = '';
00250 if( $wgRightsPage ) {
00251 $copy = Title::newFromText( $wgRightsPage );
00252 if( $copy ) {
00253 $copyright = $copy->getLocalURL();
00254 }
00255 }
00256 if( !$copyright && $wgRightsUrl ) {
00257 $copyright = $wgRightsUrl;
00258 }
00259 if( $copyright ) {
00260 $out->addLink( array(
00261 'rel' => 'copyright',
00262 'href' => $copyright ) );
00263 }
00264 }
00265
00266 function setMembers(){
00267 global $wgTitle, $wgUser;
00268 $this->mTitle = $wgTitle;
00269 $this->mUser = $wgUser;
00270 $this->userpage = $wgUser->getUserPage()->getPrefixedText();
00271 $this->usercss = false;
00272 }
00273
00274 function outputPage( OutputPage $out ) {
00275 global $wgDebugComments;
00276 wfProfileIn( __METHOD__ );
00277
00278 $this->setMembers();
00279 $this->initPage( $out );
00280
00281
00282 $afterContent = $this->afterContentHook();
00283
00284 $out->out( $out->headElement( $this ) );
00285
00286 $out->out( "\n<body" );
00287 $ops = $this->getBodyOptions();
00288 foreach ( $ops as $name => $val ) {
00289 $out->out( " $name='$val'" );
00290 }
00291 $out->out( ">\n" );
00292 if ( $wgDebugComments ) {
00293 $out->out( "<!-- Wiki debugging output:\n" .
00294 $out->mDebugtext . "-->\n" );
00295 }
00296
00297 $out->out( $this->beforeContent() );
00298
00299 $out->out( $out->mBodytext . "\n" );
00300
00301 $out->out( $this->afterContent() );
00302
00303 $out->out( $afterContent );
00304
00305 $out->out( $this->bottomScripts() );
00306
00307 $out->out( wfReportTime() );
00308
00309 $out->out( "\n</body></html>" );
00310 wfProfileOut( __METHOD__ );
00311 }
00312
00313 static function makeVariablesScript( $data ) {
00314 global $wgJsMimeType;
00315
00316 $r = array( "<script type= \"$wgJsMimeType\">/*<![CDATA[*/" );
00317 foreach ( $data as $name => $value ) {
00318 $encValue = Xml::encodeJsVar( $value );
00319 $r[] = "var $name = $encValue;";
00320 }
00321 $r[] = "/*]]>*/</script>\n";
00322
00323 return implode( "\n\t\t", $r );
00324 }
00325
00332 static function makeGlobalVariablesScript( $data ) {
00333 global $wgScript, $wgStylePath, $wgUser;
00334 global $wgArticlePath, $wgScriptPath, $wgServer, $wgContLang, $wgLang;
00335 global $wgTitle, $wgCanonicalNamespaceNames, $wgOut, $wgArticle;
00336 global $wgBreakFrames, $wgRequest, $wgVariantArticlePath, $wgActionPaths;
00337 global $wgUseAjax, $wgAjaxWatch;
00338 global $wgVersion, $wgEnableAPI, $wgEnableWriteAPI;
00339 global $wgRestrictionTypes, $wgLivePreview;
00340 global $wgMWSuggestTemplate, $wgDBname, $wgEnableMWSuggest;
00341
00342 $ns = $wgTitle->getNamespace();
00343 $nsname = isset( $wgCanonicalNamespaceNames[ $ns ] ) ? $wgCanonicalNamespaceNames[ $ns ] : $wgTitle->getNsText();
00344 $separatorTransTable = $wgContLang->separatorTransformTable();
00345 $separatorTransTable = $separatorTransTable ? $separatorTransTable : array();
00346 $compactSeparatorTransTable = array(
00347 implode( "\t", array_keys( $separatorTransTable ) ),
00348 implode( "\t", $separatorTransTable ),
00349 );
00350 $digitTransTable = $wgContLang->digitTransformTable();
00351 $digitTransTable = $digitTransTable ? $digitTransTable : array();
00352 $compactDigitTransTable = array(
00353 implode( "\t", array_keys( $digitTransTable ) ),
00354 implode( "\t", $digitTransTable ),
00355 );
00356
00357 $vars = array(
00358 'skin' => $data['skinname'],
00359 'stylepath' => $wgStylePath,
00360 'wgArticlePath' => $wgArticlePath,
00361 'wgScriptPath' => $wgScriptPath,
00362 'wgScript' => $wgScript,
00363 'wgVariantArticlePath' => $wgVariantArticlePath,
00364 'wgActionPaths' => (object)$wgActionPaths,
00365 'wgServer' => $wgServer,
00366 'wgCanonicalNamespace' => $nsname,
00367 'wgCanonicalSpecialPageName' => SpecialPage::resolveAlias( $wgTitle->getDBkey() ),
00368 'wgNamespaceNumber' => $wgTitle->getNamespace(),
00369 'wgPageName' => $wgTitle->getPrefixedDBKey(),
00370 'wgTitle' => $wgTitle->getText(),
00371 'wgAction' => $wgRequest->getText( 'action', 'view' ),
00372 'wgArticleId' => $wgTitle->getArticleId(),
00373 'wgIsArticle' => $wgOut->isArticle(),
00374 'wgUserName' => $wgUser->isAnon() ? NULL : $wgUser->getName(),
00375 'wgUserGroups' => $wgUser->isAnon() ? NULL : $wgUser->getEffectiveGroups(),
00376 'wgUserLanguage' => $wgLang->getCode(),
00377 'wgContentLanguage' => $wgContLang->getCode(),
00378 'wgBreakFrames' => $wgBreakFrames,
00379 'wgCurRevisionId' => isset( $wgArticle ) ? $wgArticle->getLatest() : 0,
00380 'wgVersion' => $wgVersion,
00381 'wgEnableAPI' => $wgEnableAPI,
00382 'wgEnableWriteAPI' => $wgEnableWriteAPI,
00383 'wgSeparatorTransformTable' => $compactSeparatorTransTable,
00384 'wgDigitTransformTable' => $compactDigitTransTable,
00385 );
00386
00387 if( $wgUseAjax && $wgEnableMWSuggest && !$wgUser->getOption( 'disablesuggest', false )){
00388 $vars['wgMWSuggestTemplate'] = SearchEngine::getMWSuggestTemplate();
00389 $vars['wgDBname'] = $wgDBname;
00390 $vars['wgSearchNamespaces'] = SearchEngine::userNamespaces( $wgUser );
00391 $vars['wgMWSuggestMessages'] = array( wfMsg('search-mwsuggest-enabled'), wfMsg('search-mwsuggest-disabled'));
00392 }
00393
00394 foreach( $wgRestrictionTypes as $type )
00395 $vars['wgRestriction' . ucfirst( $type )] = $wgTitle->getRestrictions( $type );
00396
00397 if ( $wgLivePreview && $wgUser->getOption( 'uselivepreview' ) ) {
00398 $vars['wgLivepreviewMessageLoading'] = wfMsg( 'livepreview-loading' );
00399 $vars['wgLivepreviewMessageReady'] = wfMsg( 'livepreview-ready' );
00400 $vars['wgLivepreviewMessageFailed'] = wfMsg( 'livepreview-failed' );
00401 $vars['wgLivepreviewMessageError'] = wfMsg( 'livepreview-error' );
00402 }
00403
00404 if ( $wgOut->isArticleRelated() && $wgUseAjax && $wgAjaxWatch && $wgUser->isLoggedIn() ) {
00405 $msgs = (object)array();
00406 foreach ( array( 'watch', 'unwatch', 'watching', 'unwatching' ) as $msgName ) {
00407 $msgs->{$msgName . 'Msg'} = wfMsg( $msgName );
00408 }
00409 $vars['wgAjaxWatch'] = $msgs;
00410 }
00411
00412 wfRunHooks('MakeGlobalVariablesScript', array(&$vars));
00413
00414 return self::makeVariablesScript( $vars );
00415 }
00416
00417 function getHeadScripts( $allowUserJs ) {
00418 global $wgStylePath, $wgUser, $wgJsMimeType, $wgStyleVersion;
00419
00420 $vars = self::makeGlobalVariablesScript( array( 'skinname' => $this->getSkinName() ) );
00421
00422 $r = array( "<script type=\"{$wgJsMimeType}\" src=\"{$wgStylePath}/common/wikibits.js?$wgStyleVersion\"></script>" );
00423 global $wgUseSiteJs;
00424 if ($wgUseSiteJs) {
00425 $jsCache = $wgUser->isLoggedIn() ? '&smaxage=0' : '';
00426 $r[] = "<script type=\"$wgJsMimeType\" src=\"".
00427 htmlspecialchars(self::makeUrl('-',
00428 "action=raw$jsCache&gen=js&useskin=" .
00429 urlencode( $this->getSkinName() ) ) ) .
00430 "\"><!-- site js --></script>";
00431 }
00432 if( $allowUserJs && $wgUser->isLoggedIn() ) {
00433 $userpage = $wgUser->getUserPage();
00434 $userjs = htmlspecialchars( self::makeUrl(
00435 $userpage->getPrefixedText().'/'.$this->getSkinName().'.js',
00436 'action=raw&ctype='.$wgJsMimeType));
00437 $r[] = '<script type="'.$wgJsMimeType.'" src="'.$userjs."\"></script>";
00438 }
00439 return $vars . "\t\t" . implode ( "\n\t\t", $r );
00440 }
00441
00453 function userCanPreview( $action ) {
00454 global $wgTitle, $wgRequest, $wgUser;
00455
00456 if( $action != 'submit' )
00457 return false;
00458 if( !$wgRequest->wasPosted() )
00459 return false;
00460 if( !$wgTitle->userCanEditCssJsSubpage() )
00461 return false;
00462 return $wgUser->matchEditToken(
00463 $wgRequest->getVal( 'wpEditToken' ) );
00464 }
00465
00479 public function generateUserJs() {
00480 global $wgStylePath;
00481
00482 wfProfileIn( __METHOD__ );
00483
00484 $s = "/* generated javascript */\n";
00485 $s .= "var skin = '" . Xml::escapeJsString( $this->getSkinName() ) . "';\n";
00486 $s .= "var stylepath = '" . Xml::escapeJsString( $wgStylePath ) . "';";
00487 $s .= "\n\n/* MediaWiki:Common.js */\n";
00488 $commonJs = wfMsgForContent('common.js');
00489 if ( !wfEmptyMsg ( 'common.js', $commonJs ) ) {
00490 $s .= $commonJs;
00491 }
00492
00493 $s .= "\n\n/* MediaWiki:".ucfirst( $this->getSkinName() ).".js */\n";
00494
00495
00496 $msgKey = ucfirst( $this->getSkinName() ).'.js';
00497 $userJS = wfMsgForContent($msgKey);
00498 if ( !wfEmptyMsg( $msgKey, $userJS ) ) {
00499 $s .= $userJS;
00500 }
00501
00502 wfProfileOut( __METHOD__ );
00503 return $s;
00504 }
00505
00509 public function generateUserStylesheet() {
00510 wfProfileIn( __METHOD__ );
00511 $s = "/* generated user stylesheet */\n" .
00512 $this->reallyGenerateUserStylesheet();
00513 wfProfileOut( __METHOD__ );
00514 return $s;
00515 }
00516
00520 protected function reallyGenerateUserStylesheet(){
00521 global $wgUser;
00522 $s = '';
00523 if (($undopt = $wgUser->getOption("underline")) < 2) {
00524 $underline = $undopt ? 'underline' : 'none';
00525 $s .= "a { text-decoration: $underline; }\n";
00526 }
00527 if( $wgUser->getOption( 'highlightbroken' ) ) {
00528 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
00529 } else {
00530 $s .= <<<END
00531 a.new, #quickbar a.new,
00532 a.stub, #quickbar a.stub {
00533 color: inherit;
00534 }
00535 a.new:after, #quickbar a.new:after {
00536 content: "?";
00537 color: #CC2200;
00538 }
00539 a.stub:after, #quickbar a.stub:after {
00540 content: "!";
00541 color: #772233;
00542 }
00543 END;
00544 }
00545 if( $wgUser->getOption( 'justify' ) ) {
00546 $s .= "#article, #bodyContent, #mw_content { text-align: justify; }\n";
00547 }
00548 if( !$wgUser->getOption( 'showtoc' ) ) {
00549 $s .= "#toc { display: none; }\n";
00550 }
00551 if( !$wgUser->getOption( 'editsection' ) ) {
00552 $s .= ".editsection { display: none; }\n";
00553 }
00554 return $s;
00555 }
00556
00560 function setupUserCss( OutputPage $out ) {
00561 global $wgRequest, $wgContLang, $wgUser;
00562 global $wgAllowUserCss, $wgUseSiteCss, $wgSquidMaxage, $wgStylePath;
00563
00564 wfProfileIn( __METHOD__ );
00565
00566 $this->setupSkinUserCss( $out );
00567
00568 $siteargs = array(
00569 'action' => 'raw',
00570 'maxage' => $wgSquidMaxage,
00571 );
00572
00573
00574 foreach( $out->getExtStyle() as $tag ) {
00575 $out->addStyle( $tag['href'] );
00576 }
00577
00578
00579
00580 if( $wgUseSiteCss ) {
00581 global $wgHandheldStyle;
00582 $query = wfArrayToCGI( array(
00583 'usemsgcache' => 'yes',
00584 'ctype' => 'text/css',
00585 'smaxage' => $wgSquidMaxage
00586 ) + $siteargs );
00587 # Site settings must override extension css! (bug 15025)
00588 $out->addStyle( self::makeNSUrl( 'Common.css', $query, NS_MEDIAWIKI ) );
00589 $out->addStyle( self::makeNSUrl( 'Print.css', $query, NS_MEDIAWIKI ), 'print' );
00590 if( $wgHandheldStyle ) {
00591 $out->addStyle( self::makeNSUrl( 'Handheld.css', $query, NS_MEDIAWIKI ), 'handheld' );
00592 }
00593 $out->addStyle( self::makeNSUrl( $this->getSkinName() . '.css', $query, NS_MEDIAWIKI ) );
00594 }
00595
00596 if( $wgUser->isLoggedIn() ) {
00597
00598
00599 $siteargs['smaxage'] = '0';
00600 $siteargs['ts'] = $wgUser->mTouched;
00601 }
00602
00603 $siteargs['gen'] = 'css';
00604 if( ( $us = $wgRequest->getVal( 'useskin', '' ) ) !== '' ) {
00605 $siteargs['useskin'] = $us;
00606 }
00607 $out->addStyle( self::makeUrl( '-', wfArrayToCGI( $siteargs ) ) );
00608
00609
00610 if( $wgAllowUserCss && $wgUser->isLoggedIn() ) {
00611 $action = $wgRequest->getVal('action');
00612 # If we're previewing the CSS page, use it
00613 if( $this->mTitle->isCssSubpage() && $this->userCanPreview( $action ) ) {
00614 $previewCss = $wgRequest->getText('wpTextbox1');
00615
00616 $this->usercss = "/*<![CDATA[*/\n" . $previewCss . "/*]]>*/";
00617 } else {
00618 $out->addStyle( self::makeUrl($this->userpage . '/' . $this->getSkinName() .'.css',
00619 'action=raw&ctype=text/css' ) );
00620 }
00621 }
00622
00623 wfProfileOut( __METHOD__ );
00624 }
00625
00630 function setupSkinUserCss( OutputPage $out ) {
00631 $out->addStyle( 'common/shared.css' );
00632 $out->addStyle( 'common/oldshared.css' );
00633 $out->addStyle( $this->getStylesheet() );
00634 $out->addStyle( 'common/common_rtl.css', '', '', 'rtl' );
00635 }
00636
00637 function getBodyOptions() {
00638 global $wgUser, $wgTitle, $wgOut, $wgRequest, $wgContLang;
00639
00640 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
00641
00642 if ( 0 != $wgTitle->getNamespace() ) {
00643 $a = array( 'bgcolor' => '#ffffec' );
00644 }
00645 else $a = array( 'bgcolor' => '#FFFFFF' );
00646 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
00647 $wgTitle->quickUserCan( 'edit' ) ) {
00648 $s = $wgTitle->getFullURL( $this->editUrlOptions() );
00649 $s = 'document.location = "' .Xml::escapeJsString( $s ) .'";';
00650 $a += array ('ondblclick' => $s);
00651
00652 }
00653 $a['onload'] = $wgOut->getOnloadHandler();
00654 $a['class'] =
00655 'mediawiki' .
00656 ' '.( $wgContLang->isRTL() ? "rtl" : "ltr" ).
00657 ' '.$this->getPageClasses( $wgTitle ) .
00658 ' skin-'. Sanitizer::escapeClass( $this->getSkinName( ) );
00659 return $a;
00660 }
00661
00662 function getPageClasses( $title ) {
00663 $numeric = 'ns-'.$title->getNamespace();
00664 if( $title->getNamespace() == NS_SPECIAL ) {
00665 $type = "ns-special";
00666 } elseif( $title->isTalkPage() ) {
00667 $type = "ns-talk";
00668 } else {
00669 $type = "ns-subject";
00670 }
00671 $name = Sanitizer::escapeClass( 'page-'.$title->getPrefixedText() );
00672 return "$numeric $type $name";
00673 }
00674
00678 function getLogo() {
00679 global $wgLogo;
00680 return $wgLogo;
00681 }
00682
00687 function beforeContent() {
00688 return $this->doBeforeContent();
00689 }
00690
00691 function doBeforeContent() {
00692 global $wgContLang;
00693 $fname = 'Skin::doBeforeContent';
00694 wfProfileIn( $fname );
00695
00696 $s = '';
00697 $qb = $this->qbSetting();
00698
00699 if( $langlinks = $this->otherLanguages() ) {
00700 $rows = 2;
00701 $borderhack = '';
00702 } else {
00703 $rows = 1;
00704 $langlinks = false;
00705 $borderhack = 'class="top"';
00706 }
00707
00708 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
00709 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
00710
00711 $shove = ( $qb != 0 );
00712 $left = ( $qb == 1 || $qb == 3 );
00713 if( $wgContLang->isRTL() ) $left = !$left;
00714
00715 if( !$shove ) {
00716 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
00717 $this->logoText() . '</td>';
00718 } elseif( $left ) {
00719 $s .= $this->getQuickbarCompensator( $rows );
00720 }
00721 $l = $wgContLang->isRTL() ? 'right' : 'left';
00722 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
00723
00724 $s .= $this->topLinks() ;
00725 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
00726
00727 $r = $wgContLang->isRTL() ? "left" : "right";
00728 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
00729 $s .= $this->nameAndLogin();
00730 $s .= "\n<br />" . $this->searchForm() . "</td>";
00731
00732 if ( $langlinks ) {
00733 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
00734 }
00735
00736 if ( $shove && !$left ) { # Right
00737 $s .= $this->getQuickbarCompensator( $rows );
00738 }
00739 $s .= "</tr>\n</table>\n</div>\n";
00740 $s .= "\n<div id='article'>\n";
00741
00742 $notice = wfGetSiteNotice();
00743 if( $notice ) {
00744 $s .= "\n<div id='siteNotice'>$notice</div>\n";
00745 }
00746 $s .= $this->pageTitle();
00747 $s .= $this->pageSubtitle() ;
00748 $s .= $this->getCategories();
00749 wfProfileOut( $fname );
00750 return $s;
00751 }
00752
00753
00754 function getCategoryLinks() {
00755 global $wgOut, $wgTitle, $wgUseCategoryBrowser;
00756 global $wgContLang, $wgUser;
00757
00758 if( count( $wgOut->mCategoryLinks ) == 0 ) return '';
00759
00760 # Separator
00761 $sep = wfMsgExt( 'catseparator', array( 'parsemag', 'escapenoentities' ) );
00762
00763
00764
00765 $dir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
00766 $embed = "<span dir='$dir'>";
00767 $pop = '</span>';
00768
00769 $allCats = $wgOut->getCategoryLinks();
00770 $s = '';
00771 $colon = wfMsgExt( 'colon-separator', 'escapenoentities' );
00772 if ( !empty( $allCats['normal'] ) ) {
00773 $t = $embed . implode ( "{$pop} {$sep} {$embed}" , $allCats['normal'] ) . $pop;
00774
00775 $msg = wfMsgExt( 'pagecategories', array( 'parsemag', 'escapenoentities' ), count( $allCats['normal'] ) );
00776 $s .= '<div id="mw-normal-catlinks">' .
00777 $this->link( Title::newFromText( wfMsgForContent('pagecategorieslink') ), $msg )
00778 . $colon . $t . '</div>';
00779 }
00780
00781 # Hidden categories
00782 if ( isset( $allCats['hidden'] ) ) {
00783 if ( $wgUser->getBoolOption( 'showhiddencats' ) ) {
00784 $class ='mw-hidden-cats-user-shown';
00785 } elseif ( $wgTitle->getNamespace() == NS_CATEGORY ) {
00786 $class = 'mw-hidden-cats-ns-shown';
00787 } else {
00788 $class = 'mw-hidden-cats-hidden';
00789 }
00790 $s .= "<div id=\"mw-hidden-catlinks\" class=\"$class\">" .
00791 wfMsgExt( 'hidden-categories', array( 'parsemag', 'escapenoentities' ), count( $allCats['hidden'] ) ) .
00792 $colon . $embed . implode( "$pop $sep $embed", $allCats['hidden'] ) . $pop .
00793 "</div>";
00794 }
00795
00796 # optional 'dmoz-like' category browser. Will be shown under the list
00797 # of categories an article belong to
00798 if( $wgUseCategoryBrowser ){
00799 $s .= '<br /><hr />';
00800
00801 # get a big array of the parents tree
00802 $parenttree = $wgTitle->getParentCategoryTree();
00803 # Skin object passed by reference cause it can not be
00804 # accessed under the method subfunction drawCategoryBrowser
00805 $tempout = explode("\n", Skin::drawCategoryBrowser($parenttree, $this) );
00806 # Clean out bogus first entry and sort them
00807 unset($tempout[0]);
00808 asort($tempout);
00809 # Output one per line
00810 $s .= implode("<br />\n", $tempout);
00811 }
00812
00813 return $s;
00814 }
00815
00821 function drawCategoryBrowser( $tree, &$skin ){
00822 $return = '';
00823 foreach ($tree as $element => $parent) {
00824 if (empty($parent)) {
00825 # element start a new list
00826 $return .= "\n";
00827 } else {
00828 # grab the others elements
00829 $return .= Skin::drawCategoryBrowser($parent, $skin) . ' > ';
00830 }
00831 # add our current element to the list
00832 $eltitle = Title::newFromText($element);
00833 $return .= $skin->link( $eltitle, $eltitle->getText() ) ;
00834 }
00835 return $return;
00836 }
00837
00838 function getCategories() {
00839 $catlinks=$this->getCategoryLinks();
00840
00841 $classes = 'catlinks';
00842
00843 if( strpos( $catlinks, '<div id="mw-normal-catlinks">' ) === false &&
00844 strpos( $catlinks, '<div id="mw-hidden-catlinks" class="mw-hidden-cats-hidden">' ) !== false ) {
00845 $classes .= ' catlinks-allhidden';
00846 }
00847
00848 if( !empty( $catlinks ) ){
00849 return "<div id='catlinks' class='$classes'>{$catlinks}</div>";
00850 }
00851 }
00852
00853 function getQuickbarCompensator( $rows = 1 ) {
00854 return "<td width='152' rowspan='{$rows}'> </td>";
00855 }
00856
00871 protected function afterContentHook() {
00872 $data = "";
00873
00874 if( wfRunHooks( 'SkinAfterContent', array( &$data ) ) ){
00875
00876
00877 if( trim( $data ) != '' ){
00878
00879
00880
00881 $data = "<div id='mw-data-after-content'>\n" .
00882 "\t$data\n" .
00883 "</div>\n";
00884 }
00885 } else {
00886 wfDebug( "Hook SkinAfterContent changed output processing.\n" );
00887 }
00888
00889 return $data;
00890 }
00891
00897 protected function generateDebugHTML() {
00898 global $wgShowDebug, $wgOut;
00899 if ( $wgShowDebug ) {
00900 $listInternals = str_replace( "\n", "</li>\n<li>", htmlspecialchars( $wgOut->mDebugtext ) );
00901 return "\n<hr>\n<strong>Debug data:</strong><ul style=\"font-family:monospace;\"><li>" .
00902 $listInternals . "</li></ul>\n";
00903 }
00904 return '';
00905 }
00906
00911 function afterContent() {
00912 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
00913 return $printfooter . $this->generateDebugHTML() . $this->doAfterContent();
00914 }
00915
00920 function bottomScripts() {
00921 global $wgJsMimeType;
00922 $bottomScriptText = "\n\t\t<script type=\"$wgJsMimeType\">if (window.runOnloadHook) runOnloadHook();</script>\n";
00923 wfRunHooks( 'SkinAfterBottomScripts', array( $this, &$bottomScriptText ) );
00924 return $bottomScriptText;
00925 }
00926
00928 function printSource() {
00929 global $wgTitle;
00930 $url = htmlspecialchars( $wgTitle->getFullURL() );
00931 return wfMsg( 'retrievedfrom', '<a href="'.$url.'">'.$url.'</a>' );
00932 }
00933
00934 function printFooter() {
00935 return "<p>" . $this->printSource() .
00936 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
00937 }
00938
00940 function doAfterContent() { return "</div></div>"; }
00941
00942 function pageTitleLinks() {
00943 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
00944
00945 $oldid = $wgRequest->getVal( 'oldid' );
00946 $diff = $wgRequest->getVal( 'diff' );
00947 $action = $wgRequest->getText( 'action' );
00948
00949 $s[] = $this->printableLink();
00950 $disclaimer = $this->disclaimerLink(); # may be empty
00951 if( $disclaimer ) {
00952 $s[] = $disclaimer;
00953 }
00954 $privacy = $this->privacyLink(); # may be empty too
00955 if( $privacy ) {
00956 $s[] = $privacy;
00957 }
00958
00959 if ( $wgOut->isArticleRelated() ) {
00960 if ( $wgTitle->getNamespace() == NS_FILE ) {
00961 $name = $wgTitle->getDBkey();
00962 $image = wfFindFile( $wgTitle );
00963 if( $image ) {
00964 $link = htmlspecialchars( $image->getURL() );
00965 $style = $this->getInternalLinkAttributes( $link, $name );
00966 $s[] = "<a href=\"{$link}\"{$style}>{$name}</a>";
00967 }
00968 }
00969 }
00970 if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) {
00971 $s[] .= $this->makeKnownLinkObj( $wgTitle,
00972 wfMsg( 'currentrev' ) );
00973 }
00974
00975 if ( $wgUser->getNewtalk() ) {
00976 # do not show "You have new messages" text when we are viewing our
00977 # own talk page
00978 if( !$wgTitle->equals( $wgUser->getTalkPage() ) ) {
00979 $tl = $this->makeKnownLinkObj( $wgUser->getTalkPage(), wfMsgHtml( 'newmessageslink' ), 'redirect=no' );
00980 $dl = $this->makeKnownLinkObj( $wgUser->getTalkPage(), wfMsgHtml( 'newmessagesdifflink' ), 'diff=cur' );
00981 $s[] = '<strong>'. wfMsg( 'youhavenewmessages', $tl, $dl ) . '</strong>';
00982 # disable caching
00983 $wgOut->setSquidMaxage(0);
00984 $wgOut->enableClientCache(false);
00985 }
00986 }
00987
00988 $undelete = $this->getUndeleteLink();
00989 if( !empty( $undelete ) ) {
00990 $s[] = $undelete;
00991 }
00992 return $wgLang->pipeList( $s );
00993 }
00994
00995 function getUndeleteLink() {
00996 global $wgUser, $wgTitle, $wgContLang, $wgLang, $action;
00997 if( $wgUser->isAllowed( 'deletedhistory' ) &&
00998 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
00999 ($n = $wgTitle->isDeleted() ) )
01000 {
01001 if ( $wgUser->isAllowed( 'undelete' ) ) {
01002 $msg = 'thisisdeleted';
01003 } else {
01004 $msg = 'viewdeleted';
01005 }
01006 return wfMsg( $msg,
01007 $this->makeKnownLinkObj(
01008 SpecialPage::getTitleFor( 'Undelete', $wgTitle->getPrefixedDBkey() ),
01009 wfMsgExt( 'restorelink', array( 'parsemag', 'escape' ), $wgLang->formatNum( $n ) ) ) );
01010 }
01011 return '';
01012 }
01013
01014 function printableLink() {
01015 global $wgOut, $wgFeedClasses, $wgRequest, $wgLang;
01016
01017 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
01018
01019 $s[] = "<a href=\"$printurl\" rel=\"alternate\">" . wfMsg( 'printableversion' ) . '</a>';
01020 if( $wgOut->isSyndicated() ) {
01021 foreach( $wgFeedClasses as $format => $class ) {
01022 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
01023 $s[] = "<a href=\"$feedurl\" rel=\"alternate\" type=\"application/{$format}+xml\""
01024 . " class=\"feedlink\">" . wfMsgHtml( "feed-$format" ) . "</a>";
01025 }
01026 }
01027 return $wgLang->pipeList( $s );
01028 }
01029
01030 function pageTitle() {
01031 global $wgOut;
01032 $s = '<h1 class="pagetitle">' . $wgOut->getPageTitle() . '</h1>';
01033 return $s;
01034 }
01035
01036 function pageSubtitle() {
01037 global $wgOut;
01038
01039 $sub = $wgOut->getSubtitle();
01040 if ( '' == $sub ) {
01041 global $wgExtraSubtitle;
01042 $sub = wfMsgExt( 'tagline', 'parsemag' ) . $wgExtraSubtitle;
01043 }
01044 $subpages = $this->subPageSubtitle();
01045 $sub .= !empty($subpages)?"</p><p class='subpages'>$subpages":'';
01046 $s = "<p class='subtitle'>{$sub}</p>\n";
01047 return $s;
01048 }
01049
01050 function subPageSubtitle() {
01051 $subpages = '';
01052 if(!wfRunHooks('SkinSubPageSubtitle', array(&$subpages)))
01053 return $subpages;
01054
01055 global $wgOut, $wgTitle;
01056 if($wgOut->isArticle() && MWNamespace::hasSubpages( $wgTitle->getNamespace() )) {
01057 $ptext=$wgTitle->getPrefixedText();
01058 if(preg_match('/\//',$ptext)) {
01059 $links = explode('/',$ptext);
01060 array_pop( $links );
01061 $c = 0;
01062 $growinglink = '';
01063 $display = '';
01064 foreach($links as $link) {
01065 $growinglink .= $link;
01066 $display .= $link;
01067 $linkObj = Title::newFromText( $growinglink );
01068 if( is_object( $linkObj ) && $linkObj->exists() ){
01069 $getlink = $this->makeKnownLinkObj( $linkObj, htmlspecialchars( $display ) );
01070 $c++;
01071 if ($c>1) {
01072 $subpages .= wfMsgExt( 'pipe-separator' , 'escapenoentities' );
01073 } else {
01074 $subpages .= '< ';
01075 }
01076 $subpages .= $getlink;
01077 $display = '';
01078 } else {
01079 $display .= '/';
01080 }
01081 $growinglink .= '/';
01082 }
01083 }
01084 }
01085 return $subpages;
01086 }
01087
01091 function showIPinHeader() {
01092 global $wgShowIPinHeader;
01093 return $wgShowIPinHeader && session_id() != '';
01094 }
01095
01096 function nameAndLogin() {
01097 global $wgUser, $wgTitle, $wgLang, $wgContLang;
01098
01099 $logoutPage = $wgContLang->specialPage( 'Userlogout' );
01100
01101 $ret = '';
01102 if ( $wgUser->isAnon() ) {
01103 if( $this->showIPinHeader() ) {
01104 $name = wfGetIP();
01105
01106 $talkLink = $this->link( $wgUser->getTalkPage(),
01107 $wgLang->getNsText( NS_TALK ) );
01108
01109 $ret .= "$name ($talkLink)";
01110 } else {
01111 $ret .= wfMsg( 'notloggedin' );
01112 }
01113
01114 $returnTo = $wgTitle->getPrefixedDBkey();
01115 $query = array();
01116 if ( $logoutPage != $returnTo ) {
01117 $query['returnto'] = $returnTo;
01118 }
01119
01120 $loginlink = $wgUser->isAllowed( 'createaccount' )
01121 ? 'nav-login-createaccount'
01122 : 'login';
01123 $ret .= "\n<br />" . $this->link(
01124 SpecialPage::getTitleFor( 'Userlogin' ),
01125 wfMsg( $loginlink ), array(), $query
01126 );
01127 } else {
01128 $returnTo = $wgTitle->getPrefixedDBkey();
01129 $talkLink = $this->link( $wgUser->getTalkPage(),
01130 $wgLang->getNsText( NS_TALK ) );
01131
01132 $ret .= $this->link( $wgUser->getUserPage(),
01133 htmlspecialchars( $wgUser->getName() ) );
01134 $ret .= " ($talkLink)<br />";
01135 $ret .= $wgLang->pipeList( array(
01136 $this->link(
01137 SpecialPage::getTitleFor( 'Userlogout' ), wfMsg( 'logout' ),
01138 array(), array( 'returnto' => $returnTo )
01139 ),
01140 $this->specialLink( 'preferences' ),
01141 ) );
01142 }
01143 $ret = $wgLang->pipeList( array(
01144 $ret,
01145 $this->link(
01146 Title::newFromText( wfMsgForContent( 'helppage' ) ),
01147 wfMsg( 'help' )
01148 ),
01149 ) );
01150
01151 return $ret;
01152 }
01153
01154 function getSearchLink() {
01155 $searchPage = SpecialPage::getTitleFor( 'Search' );
01156 return $searchPage->getLocalURL();
01157 }
01158
01159 function escapeSearchLink() {
01160 return htmlspecialchars( $this->getSearchLink() );
01161 }
01162
01163 function searchForm() {
01164 global $wgRequest, $wgUseTwoButtonsSearchForm;
01165 $search = $wgRequest->getText( 'search' );
01166
01167 $s = '<form id="searchform'.$this->searchboxes.'" name="search" class="inline" method="post" action="'
01168 . $this->escapeSearchLink() . "\">\n"
01169 . '<input type="text" id="searchInput'.$this->searchboxes.'" name="search" size="19" value="'
01170 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
01171 . '<input type="submit" name="go" value="' . wfMsg ('searcharticle') . '" />';
01172
01173 if ($wgUseTwoButtonsSearchForm)
01174 $s .= ' <input type="submit" name="fulltext" value="' . wfMsg ('searchbutton') . "\" />\n";
01175 else
01176 $s .= ' <a href="' . $this->escapeSearchLink() . '" rel="search">' . wfMsg ('powersearch-legend') . "</a>\n";
01177
01178 $s .= '</form>';
01179
01180
01181 $this->searchboxes = $this->searchboxes == '' ? 2 : $this->searchboxes + 1;
01182
01183 return $s;
01184 }
01185
01186 function topLinks() {
01187 global $wgOut;
01188
01189 $s = array(
01190 $this->mainPageLink(),
01191 $this->specialLink( 'recentchanges' )
01192 );
01193
01194 if ( $wgOut->isArticleRelated() ) {
01195 $s[] = $this->editThisPage();
01196 $s[] = $this->historyLink();
01197 }
01198 # Many people don't like this dropdown box
01199 #$s[] = $this->specialPagesList();
01200
01201 if( $this->variantLinks() ) {
01202 $s[] = $this->variantLinks();
01203 }
01204
01205 if( $this->extensionTabLinks() ) {
01206 $s[] = $this->extensionTabLinks();
01207 }
01208
01209
01210 return implode( $s, wfMsgExt( 'pipe-separator' , 'escapenoentities' ) . "\n" );
01211 }
01212
01219 function extensionTabLinks() {
01220 $tabs = array();
01221 $out = '';
01222 $s = array();
01223 wfRunHooks( 'SkinTemplateTabs', array( $this, &$tabs ) );
01224 foreach( $tabs as $tab ) {
01225 $s[] = Xml::element( 'a',
01226 array( 'href' => $tab['href'] ),
01227 $tab['text'] );
01228 }
01229
01230 if( count( $s ) ) {
01231 global $wgLang;
01232
01233 $out = wfMsgExt( 'pipe-separator' , 'escapenoentities' );
01234 $out .= $wgLang->pipeList( $s );
01235 }
01236
01237 return $out;
01238 }
01239
01244 function variantLinks() {
01245 $s = '';
01246
01247 global $wgDisableLangConversion, $wgLang, $wgContLang, $wgTitle;
01248 $variants = $wgContLang->getVariants();
01249 if( !$wgDisableLangConversion && sizeof( $variants ) > 1 ) {
01250 foreach( $variants as $code ) {
01251 $varname = $wgContLang->getVariantname( $code );
01252 if( $varname == 'disable' )
01253 continue;
01254 $s = $wgLang->pipeList( array( $s, '<a href="' . $wgTitle->escapeLocalUrl( 'variant=' . $code ) . '">' . htmlspecialchars( $varname ) . '</a>' ) );
01255 }
01256 }
01257 return $s;
01258 }
01259
01260 function bottomLinks() {
01261 global $wgOut, $wgUser, $wgTitle, $wgUseTrackbacks;
01262 $sep = wfMsgExt( 'pipe-separator' , 'escapenoentities' ) . "\n";
01263
01264 $s = '';
01265 if ( $wgOut->isArticleRelated() ) {
01266 $element[] = '<strong>' . $this->editThisPage() . '</strong>';
01267 if ( $wgUser->isLoggedIn() ) {
01268 $element[] = $this->watchThisPage();
01269 }
01270 $element[] = $this->talkLink();
01271 $element[] = $this->historyLink();
01272 $element[] = $this->whatLinksHere();
01273 $element[] = $this->watchPageLinksLink();
01274
01275 if ($wgUseTrackbacks)
01276 $element[] = $this->trackbackLink();
01277
01278 if ( $wgTitle->getNamespace() == NS_USER
01279 || $wgTitle->getNamespace() == NS_USER_TALK )
01280
01281 {
01282 $id=User::idFromName($wgTitle->getText());
01283 $ip=User::isIP($wgTitle->getText());
01284
01285 if($id || $ip) { # both anons and non-anons have contri list
01286 $element[] = $this->userContribsLink();
01287 }
01288 if( $this->showEmailUser( $id ) ) {
01289 $element[] = $this->emailUserLink();
01290 }
01291 }
01292
01293 $s = implode( $element, $sep );
01294
01295 if ( $wgTitle->getArticleId() ) {
01296 $s .= "\n<br />";
01297 if($wgUser->isAllowed('delete')) { $s .= $this->deleteThisPage(); }
01298 if($wgUser->isAllowed('protect')) { $s .= $sep . $this->protectThisPage(); }
01299 if($wgUser->isAllowed('move')) { $s .= $sep . $this->moveThisPage(); }
01300 }
01301 $s .= "<br />\n" . $this->otherLanguages();
01302 }
01303
01304 return $s;
01305 }
01306
01307 function pageStats() {
01308 global $wgOut, $wgLang, $wgArticle, $wgRequest, $wgUser;
01309 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax, $wgTitle, $wgPageShowWatchingUsers;
01310
01311 $oldid = $wgRequest->getVal( 'oldid' );
01312 $diff = $wgRequest->getVal( 'diff' );
01313 if ( ! $wgOut->isArticle() ) { return ''; }
01314 if( !$wgArticle instanceOf Article ) { return ''; }
01315 if ( isset( $oldid ) || isset( $diff ) ) { return ''; }
01316 if ( 0 == $wgArticle->getID() ) { return ''; }
01317
01318 $s = '';
01319 if ( !$wgDisableCounters ) {
01320 $count = $wgLang->formatNum( $wgArticle->getCount() );
01321 if ( $count ) {
01322 $s = wfMsgExt( 'viewcount', array( 'parseinline' ), $count );
01323 }
01324 }
01325
01326 if( $wgMaxCredits != 0 ){
01327 $s .= ' ' . Credits::getCredits( $wgArticle, $wgMaxCredits, $wgShowCreditsIfMax );
01328 } else {
01329 $s .= $this->lastModified();
01330 }
01331
01332 if( $wgPageShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' ) ) {
01333 $dbr = wfGetDB( DB_SLAVE );
01334 $watchlist = $dbr->tableName( 'watchlist' );
01335 $sql = "SELECT COUNT(*) AS n FROM $watchlist
01336 WHERE wl_title='" . $dbr->strencode($wgTitle->getDBkey()) .
01337 "' AND wl_namespace=" . $wgTitle->getNamespace() ;
01338 $res = $dbr->query( $sql, 'Skin::pageStats');
01339 $x = $dbr->fetchObject( $res );
01340
01341 $s .= ' ' . wfMsgExt( 'number_of_watching_users_pageview',
01342 array( 'parseinline' ), $wgLang->formatNum($x->n)
01343 );
01344 }
01345
01346 return $s . ' ' . $this->getCopyright();
01347 }
01348
01349 function getCopyright( $type = 'detect' ) {
01350 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest, $wgArticle;
01351
01352 if ( $type == 'detect' ) {
01353 $diff = $wgRequest->getVal( 'diff' );
01354 $isCur = $wgArticle && $wgArticle->isCurrent();
01355 if ( is_null( $diff ) && !$isCur && wfMsgForContent( 'history_copyright' ) !== '-' ) {
01356 $type = 'history';
01357 } else {
01358 $type = 'normal';
01359 }
01360 }
01361
01362 if ( $type == 'history' ) {
01363 $msg = 'history_copyright';
01364 } else {
01365 $msg = 'copyright';
01366 }
01367
01368 $out = '';
01369 if( $wgRightsPage ) {
01370 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
01371 } elseif( $wgRightsUrl ) {
01372 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
01373 } elseif( $wgRightsText ) {
01374 $link = $wgRightsText;
01375 } else {
01376 # Give up now
01377 return $out;
01378 }
01379 $out .= wfMsgForContent( $msg, $link );
01380 return $out;
01381 }
01382
01383 function getCopyrightIcon() {
01384 global $wgRightsUrl, $wgRightsText, $wgRightsIcon, $wgCopyrightIcon;
01385 $out = '';
01386 if ( isset( $wgCopyrightIcon ) && $wgCopyrightIcon ) {
01387 $out = $wgCopyrightIcon;
01388 } else if ( $wgRightsIcon ) {
01389 $icon = htmlspecialchars( $wgRightsIcon );
01390 if ( $wgRightsUrl ) {
01391 $url = htmlspecialchars( $wgRightsUrl );
01392 $out .= '<a href="'.$url.'">';
01393 }
01394 $text = htmlspecialchars( $wgRightsText );
01395 $out .= "<img src=\"$icon\" alt='$text' />";
01396 if ( $wgRightsUrl ) {
01397 $out .= '</a>';
01398 }
01399 }
01400 return $out;
01401 }
01402
01403 function getPoweredBy() {
01404 global $wgStylePath;
01405 $url = htmlspecialchars( "$wgStylePath/common/images/poweredby_mediawiki_88x31.png" );
01406 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="Powered by MediaWiki" /></a>';
01407 return $img;
01408 }
01409
01410 function lastModified() {
01411 global $wgLang, $wgArticle;
01412 if( $this->mRevisionId ) {
01413 $timestamp = Revision::getTimestampFromId( $wgArticle->getTitle(), $this->mRevisionId );
01414 } else {
01415 $timestamp = $wgArticle->getTimestamp();
01416 }
01417 if ( $timestamp ) {
01418 $d = $wgLang->date( $timestamp, true );
01419 $t = $wgLang->time( $timestamp, true );
01420 $s = ' ' . wfMsg( 'lastmodifiedat', $d, $t );
01421 } else {
01422 $s = '';
01423 }
01424 if ( wfGetLB()->getLaggedSlaveMode() ) {
01425 $s .= ' <strong>' . wfMsg( 'laggedslavemode' ) . '</strong>';
01426 }
01427 return $s;
01428 }
01429
01430 function logoText( $align = '' ) {
01431 if ( '' != $align ) { $a = " align='{$align}'"; }
01432 else { $a = ''; }
01433
01434 $mp = wfMsg( 'mainpage' );
01435 $mptitle = Title::newMainPage();
01436 $url = ( is_object($mptitle) ? $mptitle->escapeLocalURL() : '' );
01437
01438 $logourl = $this->getLogo();
01439 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
01440 return $s;
01441 }
01442
01446 function specialPagesList() {
01447 global $wgUser, $wgContLang, $wgServer, $wgRedirectScript;
01448 $pages = array_merge( SpecialPage::getRegularPages(), SpecialPage::getRestrictedPages() );
01449 foreach ( $pages as $name => $page ) {
01450 $pages[$name] = $page->getDescription();
01451 }
01452
01453 $go = wfMsg( 'go' );
01454 $sp = wfMsg( 'specialpages' );
01455 $spp = $wgContLang->specialPage( 'Specialpages' );
01456
01457 $s = '<form id="specialpages" method="get" ' .
01458 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
01459 $s .= "<select name=\"wpDropdown\">\n";
01460 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
01461
01462
01463 foreach ( $pages as $name => $desc ) {
01464 $p = $wgContLang->specialPage( $name );
01465 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
01466 }
01467 $s .= "</select>\n";
01468 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
01469 $s .= "</form>\n";
01470 return $s;
01471 }
01472
01473 function mainPageLink() {
01474 $s = $this->makeKnownLinkObj( Title::newMainPage(), wfMsg( 'mainpage' ) );
01475 return $s;
01476 }
01477
01478 function copyrightLink() {
01479 $s = $this->makeKnownLink( wfMsgForContent( 'copyrightpage' ),
01480 wfMsg( 'copyrightpagename' ) );
01481 return $s;
01482 }
01483
01484 private function footerLink ( $desc, $page ) {
01485
01486 if ( wfMsgForContent( $desc ) == '-') {
01487
01488 return '';
01489 } else {
01490
01491
01492
01493 return $this->makeKnownLink( wfMsgForContent( $page ),
01494 wfMsgExt( $desc, array( 'parsemag', 'escapenoentities' ) ) );
01495 }
01496 }
01497
01498 function privacyLink() {
01499 return $this->footerLink( 'privacy', 'privacypage' );
01500 }
01501
01502 function aboutLink() {
01503 return $this->footerLink( 'aboutsite', 'aboutpage' );
01504 }
01505
01506 function disclaimerLink() {
01507 return $this->footerLink( 'disclaimers', 'disclaimerpage' );
01508 }
01509
01510 function editThisPage() {
01511 global $wgOut, $wgTitle;
01512
01513 if ( !$wgOut->isArticleRelated() ) {
01514 $s = wfMsg( 'protectedpage' );
01515 } else {
01516 if( $wgTitle->quickUserCan( 'edit' ) && $wgTitle->exists() ) {
01517 $t = wfMsg( 'editthispage' );
01518 } elseif( $wgTitle->quickUserCan( 'create' ) && !$wgTitle->exists() ) {
01519 $t = wfMsg( 'create-this-page' );
01520 } else {
01521 $t = wfMsg( 'viewsource' );
01522 }
01523
01524 $s = $this->makeKnownLinkObj( $wgTitle, $t, $this->editUrlOptions() );
01525 }
01526 return $s;
01527 }
01528
01536 function editUrlOptions() {
01537 global $wgArticle;
01538
01539 if( $this->mRevisionId && ! $wgArticle->isCurrent() ) {
01540 return "action=edit&oldid=" . intval( $this->mRevisionId );
01541 } else {
01542 return "action=edit";
01543 }
01544 }
01545
01546 function deleteThisPage() {
01547 global $wgUser, $wgTitle, $wgRequest;
01548
01549 $diff = $wgRequest->getVal( 'diff' );
01550 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isAllowed('delete') ) {
01551 $t = wfMsg( 'deletethispage' );
01552
01553 $s = $this->makeKnownLinkObj( $wgTitle, $t, 'action=delete' );
01554 } else {
01555 $s = '';
01556 }
01557 return $s;
01558 }
01559
01560 function protectThisPage() {
01561 global $wgUser, $wgTitle, $wgRequest;
01562
01563 $diff = $wgRequest->getVal( 'diff' );
01564 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isAllowed('protect') ) {
01565 if ( $wgTitle->isProtected() ) {
01566 $t = wfMsg( 'unprotectthispage' );
01567 $q = 'action=unprotect';
01568 } else {
01569 $t = wfMsg( 'protectthispage' );
01570 $q = 'action=protect';
01571 }
01572 $s = $this->makeKnownLinkObj( $wgTitle, $t, $q );
01573 } else {
01574 $s = '';
01575 }
01576 return $s;
01577 }
01578
01579 function watchThisPage() {
01580 global $wgOut, $wgTitle;
01581 ++$this->mWatchLinkNum;
01582
01583 if ( $wgOut->isArticleRelated() ) {
01584 if ( $wgTitle->userIsWatching() ) {
01585 $t = wfMsg( 'unwatchthispage' );
01586 $q = 'action=unwatch';
01587 $id = "mw-unwatch-link".$this->mWatchLinkNum;
01588 } else {
01589 $t = wfMsg( 'watchthispage' );
01590 $q = 'action=watch';
01591 $id = 'mw-watch-link'.$this->mWatchLinkNum;
01592 }
01593 $s = $this->makeKnownLinkObj( $wgTitle, $t, $q, '', '', " id=\"$id\"" );
01594 } else {
01595 $s = wfMsg( 'notanarticle' );
01596 }
01597 return $s;
01598 }
01599
01600 function moveThisPage() {
01601 global $wgTitle;
01602
01603 if ( $wgTitle->quickUserCan( 'move' ) ) {
01604 return $this->makeKnownLinkObj( SpecialPage::getTitleFor( 'Movepage' ),
01605 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
01606 } else {
01607
01608 return '';
01609 }
01610 }
01611
01612 function historyLink() {
01613 global $wgTitle;
01614
01615 return $this->link( $wgTitle, wfMsg( 'history' ),
01616 array( 'rel' => 'archives' ), array( 'action' => 'history' ) );
01617 }
01618
01619 function whatLinksHere() {
01620 global $wgTitle;
01621
01622 return $this->makeKnownLinkObj(
01623 SpecialPage::getTitleFor( 'Whatlinkshere', $wgTitle->getPrefixedDBkey() ),
01624 wfMsg( 'whatlinkshere' ) );
01625 }
01626
01627 function userContribsLink() {
01628 global $wgTitle;
01629
01630 return $this->makeKnownLinkObj(
01631 SpecialPage::getTitleFor( 'Contributions', $wgTitle->getDBkey() ),
01632 wfMsg( 'contributions' ) );
01633 }
01634
01635 function showEmailUser( $id ) {
01636 global $wgUser;
01637 $targetUser = User::newFromId( $id );
01638 return $wgUser->canSendEmail() && # the sending user must have a confirmed email address
01639 $targetUser->canReceiveEmail(); # the target user must have a confirmed email address and allow emails from users
01640 }
01641
01642 function emailUserLink() {
01643 global $wgTitle;
01644
01645 return $this->makeKnownLinkObj(
01646 SpecialPage::getTitleFor( 'Emailuser', $wgTitle->getDBkey() ),
01647 wfMsg( 'emailuser' ) );
01648 }
01649
01650 function watchPageLinksLink() {
01651 global $wgOut, $wgTitle;
01652
01653 if ( ! $wgOut->isArticleRelated() ) {
01654 return '(' . wfMsg( 'notanarticle' ) . ')';
01655 } else {
01656 return $this->makeKnownLinkObj(
01657 SpecialPage::getTitleFor( 'Recentchangeslinked', $wgTitle->getPrefixedDBkey() ),
01658 wfMsg( 'recentchangeslinked' ) );
01659 }
01660 }
01661
01662 function trackbackLink() {
01663 global $wgTitle;
01664
01665 return "<a href=\"" . $wgTitle->trackbackURL() . "\">"
01666 . wfMsg('trackbacklink') . "</a>";
01667 }
01668
01669 function otherLanguages() {
01670 global $wgOut, $wgContLang, $wgHideInterlanguageLinks;
01671
01672 if ( $wgHideInterlanguageLinks ) {
01673 return '';
01674 }
01675
01676 $a = $wgOut->getLanguageLinks();
01677 if ( 0 == count( $a ) ) {
01678 return '';
01679 }
01680
01681 $s = wfMsg( 'otherlanguages' ) . wfMsg( 'colon-separator' );
01682 $first = true;
01683 if($wgContLang->isRTL()) $s .= '<span dir="LTR">';
01684 foreach( $a as $l ) {
01685 if ( ! $first ) { $s .= wfMsgExt( 'pipe-separator' , 'escapenoentities' ); }
01686 $first = false;
01687
01688 $nt = Title::newFromText( $l );
01689 $url = $nt->escapeFullURL();
01690 $text = $wgContLang->getLanguageName( $nt->getInterwiki() );
01691
01692 if ( '' == $text ) { $text = $l; }
01693 $style = $this->getExternalLinkAttributes( $l, $text );
01694 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
01695 }
01696 if($wgContLang->isRTL()) $s .= '</span>';
01697 return $s;
01698 }
01699
01700 function talkLink() {
01701 global $wgTitle;
01702
01703 if ( NS_SPECIAL == $wgTitle->getNamespace() ) {
01704 # No discussion links for special pages
01705 return '';
01706 }
01707
01708 $linkOptions = array();
01709
01710 if( $wgTitle->isTalkPage() ) {
01711 $link = $wgTitle->getSubjectPage();
01712 switch( $link->getNamespace() ) {
01713 case NS_MAIN:
01714 $text = wfMsg( 'articlepage' );
01715 break;
01716 case NS_USER:
01717 $text = wfMsg( 'userpage' );
01718 break;
01719 case NS_PROJECT:
01720 $text = wfMsg( 'projectpage' );
01721 break;
01722 case NS_FILE:
01723 $text = wfMsg( 'imagepage' );
01724 # Make link known if image exists, even if the desc. page doesn't.
01725 if( wfFindFile( $link ) )
01726 $linkOptions[] = 'known';
01727 break;
01728 case NS_MEDIAWIKI:
01729 $text = wfMsg( 'mediawikipage' );
01730 break;
01731 case NS_TEMPLATE:
01732 $text = wfMsg( 'templatepage' );
01733 break;
01734 case NS_HELP:
01735 $text = wfMsg( 'viewhelppage' );
01736 break;
01737 case NS_CATEGORY:
01738 $text = wfMsg( 'categorypage' );
01739 break;
01740 default:
01741 $text = wfMsg( 'articlepage' );
01742 }
01743 } else {
01744 $link = $wgTitle->getTalkPage();
01745 $text = wfMsg( 'talkpage' );
01746 }
01747
01748 $s = $this->link( $link, $text, array(), array(), $linkOptions );
01749
01750 return $s;
01751 }
01752
01753 function commentLink() {
01754 global $wgTitle, $wgOut;
01755
01756 if ( $wgTitle->getNamespace() == NS_SPECIAL ) {
01757 return '';
01758 }
01759
01760 # __NEWSECTIONLINK___ changes behaviour here
01761 # If it's present, the link points to this page, otherwise
01762 # it points to the talk page
01763 if( $wgTitle->isTalkPage() ) {
01764 $title = $wgTitle;
01765 } elseif( $wgOut->showNewSectionLink() ) {
01766 $title = $wgTitle;
01767 } else {
01768 $title = $wgTitle->getTalkPage();
01769 }
01770
01771 return $this->makeKnownLinkObj( $title, wfMsg( 'postcomment' ), 'action=edit§ion=new' );
01772 }
01773
01774
01775 static function makeMainPageUrl( $urlaction = '' ) {
01776 $title = Title::newMainPage();
01777 self::checkTitle( $title, '' );
01778 return $title->getLocalURL( $urlaction );
01779 }
01780
01781 static function makeSpecialUrl( $name, $urlaction = '' ) {
01782 $title = SpecialPage::getTitleFor( $name );
01783 return $title->getLocalURL( $urlaction );
01784 }
01785
01786 static function makeSpecialUrlSubpage( $name, $subpage, $urlaction = '' ) {
01787 $title = SpecialPage::getSafeTitleFor( $name, $subpage );
01788 return $title->getLocalURL( $urlaction );
01789 }
01790
01791 static function makeI18nUrl( $name, $urlaction = '' ) {
01792 $title = Title::newFromText( wfMsgForContent( $name ) );
01793 self::checkTitle( $title, $name );
01794 return $title->getLocalURL( $urlaction );
01795 }
01796
01797 static function makeUrl( $name, $urlaction = '' ) {
01798 $title = Title::newFromText( $name );
01799 self::checkTitle( $title, $name );
01800 return $title->getLocalURL( $urlaction );
01801 }
01802
01803 # If url string starts with http, consider as external URL, else
01804 # internal
01805 static function makeInternalOrExternalUrl( $name ) {
01806 if ( preg_match( '/^(?:' . wfUrlProtocols() . ')/', $name ) ) {
01807 return $name;
01808 } else {
01809 return self::makeUrl( $name );
01810 }
01811 }
01812
01813 # this can be passed the NS number as defined in Language.php
01814 static function makeNSUrl( $name, $urlaction = '', $namespace = NS_MAIN ) {
01815 $title = Title::makeTitleSafe( $namespace, $name );
01816 self::checkTitle( $title, $name );
01817 return $title->getLocalURL( $urlaction );
01818 }
01819
01820
01821 static function makeUrlDetails( $name, $urlaction = '' ) {
01822 $title = Title::newFromText( $name );
01823 self::checkTitle( $title, $name );
01824 return array(
01825 'href' => $title->getLocalURL( $urlaction ),
01826 'exists' => $title->getArticleID() != 0 ? true : false
01827 );
01828 }
01829
01833 static function makeKnownUrlDetails( $name, $urlaction = '' ) {
01834 $title = Title::newFromText( $name );
01835 self::checkTitle( $title, $name );
01836 return array(
01837 'href' => $title->getLocalURL( $urlaction ),
01838 'exists' => true
01839 );
01840 }
01841
01842 # make sure we have some title to operate on
01843 static function checkTitle( &$title, $name ) {
01844 if( !is_object( $title ) ) {
01845 $title = Title::newFromText( $name );
01846 if( !is_object( $title ) ) {
01847 $title = Title::newFromText( '--error: link target missing--' );
01848 }
01849 }
01850 }
01851
01857 function buildSidebar() {
01858 global $parserMemc, $wgEnableSidebarCache, $wgSidebarCacheExpiry;
01859 global $wgLang;
01860 wfProfileIn( __METHOD__ );
01861
01862 $key = wfMemcKey( 'sidebar', $wgLang->getCode() );
01863
01864 if ( $wgEnableSidebarCache ) {
01865 $cachedsidebar = $parserMemc->get( $key );
01866 if ( $cachedsidebar ) {
01867 wfProfileOut( __METHOD__ );
01868 return $cachedsidebar;
01869 }
01870 }
01871
01872 $bar = array();
01873 $lines = explode( "\n", wfMsgForContent( 'sidebar' ) );
01874 $heading = '';
01875 foreach ($lines as $line) {
01876 if (strpos($line, '*') !== 0)
01877 continue;
01878 if (strpos($line, '**') !== 0) {
01879 $line = trim($line, '* ');
01880 $heading = $line;
01881 if( !array_key_exists($heading, $bar) ) $bar[$heading] = array();
01882 } else {
01883 if (strpos($line, '|') !== false) {
01884 $line = array_map('trim', explode( '|' , trim($line, '* '), 2 ) );
01885 $link = wfMsgForContent( $line[0] );
01886 if ($link == '-')
01887 continue;
01888
01889 $text = wfMsgExt($line[1], 'parsemag');
01890 if (wfEmptyMsg($line[1], $text))
01891 $text = $line[1];
01892 if (wfEmptyMsg($line[0], $link))
01893 $link = $line[0];
01894
01895 if ( preg_match( '/^(?:' . wfUrlProtocols() . ')/', $link ) ) {
01896 $href = $link;
01897 } else {
01898 $title = Title::newFromText( $link );
01899 if ( $title ) {
01900 $title = $title->fixSpecialName();
01901 $href = $title->getLocalURL();
01902 } else {
01903 $href = 'INVALID-TITLE';
01904 }
01905 }
01906
01907 $bar[$heading][] = array(
01908 'text' => $text,
01909 'href' => $href,
01910 'id' => 'n-' . strtr($line[1], ' ', '-'),
01911 'active' => false
01912 );
01913 } else { continue; }
01914 }
01915 }
01916 wfRunHooks('SkinBuildSidebar', array($this, &$bar));
01917 if ( $wgEnableSidebarCache ) $parserMemc->set( $key, $bar, $wgSidebarCacheExpiry );
01918 wfProfileOut( __METHOD__ );
01919 return $bar;
01920 }
01921 }