Fix double-compression; fix missing deletion reason; fix html insertion attack; fix...
[mediawiki.git] / includes / Skin.php
blobc1c3e3144c8f6f5a1502630d435468dd5beeb548
1 <?
2 # See skin.doc
4 # These are the INTERNAL names, which get mapped
5 # directly to class names. For display purposes, the
6 # Language class has internationalized names
8 /* private */ $wgValidSkinNames = array(
9 "Standard", "Nostalgia", "CologneBlue" #, "Smarty", "Montparnasse"
12 # For some odd PHP bug, this function can't be part of a class
13 function getCategories ()
15 global $wgOut , $wgTitle , $wgUseCategoryMagic , $wgUser ;
16 if ( !isset ( $wgUseCategoryMagic ) || !$wgUseCategoryMagic ) return "" ;
17 if ( count ( $wgOut->mCategoryLinks ) == 0 ) return "" ;
18 if ( !$wgOut->isArticle() ) return "" ;
19 $sk = $wgUser->getSkin() ;
20 $s = "" ;
21 $s .= "\n<br>\n";
22 $s .= $sk->makeKnownLink ( "Special:Categories" , "Categories" , "article=".$wgTitle->getDBkey() ) ;
23 $t = implode ( " | " , $wgOut->mCategoryLinks ) ;
24 if ( $t != "" ) $s .= " : " ;
25 $s .= $t ;
26 return $s ;
30 class RecentChangesClass {
31 var $secureName , $displayName , $link , $namespace ;
32 var $oldid , $diffid , $timestamp , $curlink , $lastlink , $usertalklink , $versionlink ;
33 var $usercomment , $userlink ;
34 var $isminor , $isnew , $watched , $islog ;
35 } ;
37 class Skin {
39 /* private */ var $lastdate, $lastline;
41 var $rc_cache ; # Cache for Enhanced Recent Changes
42 var $rccc ; # Recent Changes Cache Counter for visibility toggle
45 function Skin()
49 function getSkinNames()
51 global $wgValidSkinNames;
52 return $wgValidSkinNames;
55 function getStylesheet()
57 return "wikistandard.css";
60 function qbSetting()
62 global $wgOut, $wgUser;
64 if ( $wgOut->isQuickbarSupressed() ) { return 0; }
65 $q = $wgUser->getOption( "quickbar" );
66 if ( "" == $q ) { $q = 0; }
67 return $q;
70 function initPage()
72 global $wgOut, $wgStyleSheetPath;
73 $fname = "Skin::initPage";
74 wfProfileIn( $fname );
76 $wgOut->addLink( "shortcut icon", "", "/favicon.ico" );
77 if ( $wgOut->isPrintable() ) { $ss = "wikiprintable.css"; }
78 else { $ss = $this->getStylesheet(); }
79 $wgOut->addLink( "stylesheet", "", "{$wgStyleSheetPath}/{$ss}" );
80 wfProfileOut( $fname );
83 function outputPage( &$out ) {
84 wfProfileIn( "Skin::outputPage" );
85 $this->initPage();
86 $out->out( $out->headElement() );
88 $out->out( "\n<body" );
89 $ops = $this->getBodyOptions();
90 foreach ( $ops as $name => $val ) {
91 $out->out( " $name='$val'" );
93 $out->out( ">\n" );
94 if ( $wgDebugComments ) {
95 $out->out( "<!-- Wiki debugging output:\n" .
96 $out->mDebugtext . "-->\n" );
98 $out->out( $this->beforeContent() );
100 $out->out( $out->mBodytext );
102 $out->out( $this->afterContent() );
104 wfProfileClose();
105 $out->out( $out->reportTime() );
107 $out->out( "\n</body></html>" );
110 function getHeadScripts() {
111 global $wgStyleSheetPath;
112 $r = "<script type=\"text/javascript\" src=\"{$wgStyleSheetPath}/wikibits.js\"></script>\n";
113 return $r;
116 function getUserStyles()
118 $s = "<style type='text/css'><!--\n";
119 $s .= $this->doGetUserStyles();
120 $s .= "//--></style>\n";
121 return $s;
124 function doGetUserStyles()
126 global $wgUser;
128 $s = "";
129 if ( 1 == $wgUser->getOption( "underline" ) ) {
130 # Don't override browser settings
131 } else {
132 # CHECK MERGE @@@
133 # Force no underline
134 $s .= "a.stub, a.new, a.internal, a.external { " .
135 "text-decoration: none; }\n";
137 if ( 1 == $wgUser->getOption( "highlightbroken" ) ) {
138 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
140 if ( 1 == $wgUser->getOption( "justify" ) ) {
141 $s .= "#article { text-align: justify; }\n";
143 return $s;
146 function getBodyOptions()
148 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $oldid, $redirect, $diff,$action;
150 if ( 0 != $wgTitle->getNamespace() ) {
151 $a = array( "bgcolor" => "#ffffec" );
153 else $a = array( "bgcolor" => "#FFFFFF" );
154 if($wgOut->isArticle() && $wgUser->getOption("editondblclick")
156 (!$wgTitle->isProtected() || $wgUser->isSysop())
159 $n = $wgTitle->getPrefixedURL();
160 $t = wfMsg( "editthispage" );
161 $oid = $red = "";
162 if ( $redirect ) { $red = "&redirect={$redirect}"; }
163 if ( $oldid && ! isset( $diff ) ) {
164 $oid = "&oldid={$oldid}";
166 $s = wfLocalUrlE($n,"action=edit{$oid}{$red}");
167 $s = "document.location = \"" .$s ."\";";
168 $a += array ("ondblclick" => $s);
171 if($action=="edit") { # set focus in edit box
172 $foc = "document.editform.wpTextbox1.focus()";
173 if($a['onload']) {
174 $a['onload'] .= ";$foc";
175 } else {
176 $a['onload'] = $foc;
179 return $a;
182 function getExternalLinkAttributes( $link, $text )
184 global $wgUser, $wgOut, $wgLang;
186 $link = urldecode( $link );
187 $link = $wgLang->checkTitleEncoding( $link );
188 $link = str_replace( "_", " ", $link );
189 $link = wfEscapeHTML( $link );
191 if ( $wgOut->isPrintable() ) { $r = " class='printable'"; }
192 else { $r = " class='external'"; }
194 if ( 1 == $wgUser->getOption( "hover" ) ) {
195 $r .= " title=\"{$link}\"";
197 return $r;
200 function getInternalLinkAttributes( $link, $text, $broken = false )
202 global $wgUser, $wgOut;
204 $link = urldecode( $link );
205 $link = str_replace( "_", " ", $link );
206 $link = wfEscapeHTML( $link );
208 if ( $wgOut->isPrintable() ) {
209 $r = " class='printable'";
210 } else if ( $broken == "stub" ) {
211 $r = " class='stub'";
212 } else if ( $broken == "yes" ) {
213 $r = " class='new'";
214 } else {
215 $r = " class='internal'";
218 if ( 1 == $wgUser->getOption( "hover" ) ) {
219 $r .= " title=\"{$link}\"";
221 return $r;
224 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
226 global $wgUser, $wgOut;
228 if ( $wgOut->isPrintable() ) {
229 $r = " class='printable'";
230 } else if ( $broken == "stub" ) {
231 $r = " class='stub'";
232 } else if ( $broken == "yes" ) {
233 $r = " class='new'";
234 } else {
235 $r = " class='internal'";
238 if ( 1 == $wgUser->getOption( "hover" ) ) {
239 $r .= ' title ="' . $nt->getEscapedText() . '"';
241 return $r;
244 function getLogo()
246 global $wgLogo;
247 return $wgLogo;
250 # This will be called immediately after the <body> tag. Split into
251 # two functions to make it easier to subclass.
253 function beforeContent()
255 global $wgUser, $wgOut;
257 if ( $wgOut->isPrintable() ) {
258 $s = $this->pageTitle() . $this->pageSubtitle() . "\n";
259 $s .= "\n<div class='bodytext'>";
260 return $s;
262 return $this->doBeforeContent();
265 function doBeforeContent()
267 global $wgUser, $wgOut, $wgTitle, $wgLang;
268 $fname = "Skin::doBeforeContent";
269 wfProfileIn( $fname );
271 $s = "";
272 $qb = $this->qbSetting();
274 if( $langlinks = $this->otherLanguages() ) {
275 $rows = 2;
276 $borderhack = "";
277 } else {
278 $rows = 1;
279 $langlinks = false;
280 $borderhack = "class='top'";
283 $s .= "\n<div id='content'>\n<div id='topbar'>" .
284 "<table width='98%' border=0 cellspacing=0><tr>";
286 $shove = ($qb != 0);
287 $left = ($qb == 1 || $qb == 3);
288 if($wgLang->isRTL()) $left = !$left;
290 if ( !$shove ) {
291 $s .= "<td class='top' align=left valign=top rowspan='{$rows}'>" .
292 $this->logoText() . "</td>";
293 } elseif( $left ) {
294 $s .= $this->getQuickbarCompensator( $rows );
296 $l = $wgLang->isRTL() ? "right" : "left";
297 $s .= "<td {$borderhack} align='$l' valign='top'>";
299 $s .= $this->topLinks() ;
300 $s .= "<p class='subtitle'>" . $this->pageTitleLinks();
302 $r = $wgLang->isRTL() ? "left" : "right";
303 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap>";
304 $s .= $this->nameAndLogin();
305 $s .= "\n<br>" . $this->searchForm() . "</td>";
307 if ( $langlinks ) {
308 $s .= "</tr>\n<tr><td class='top' colspan=\"2\">$langlinks</td>";
311 if ( $shove && !$left ) { # Right
312 $s .= $this->getQuickbarCompensator( $rows );
314 $s .= "</tr></table>\n</div>\n";
315 $s .= "\n<div id='article'>";
317 $s .= $this->pageTitle();
318 $s .= $this->pageSubtitle() ;
319 $s .= getCategories(); // For some odd reason, zhis can't be a function of the object
320 $s .= "\n<p>";
321 wfProfileOut( $fname );
322 return $s;
325 function getQuickbarCompensator( $rows = 1 )
327 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
330 # This gets called immediately before the </body> tag.
332 function afterContent()
334 global $wgUser, $wgOut, $wgServer;
335 global $wgTitle;
337 if ( $wgOut->isPrintable() ) {
338 $s = "\n</div>\n";
340 $u = htmlspecialchars( $wgServer . $wgTitle->getFullURL() );
341 $u = "<a href=\"$u\">$u</a>";
342 $rf = wfMsg( "retrievedfrom", $u );
344 if ( $wgOut->isArticle() ) {
345 $lm = "<br>" . $this->lastModified();
346 } else { $lm = ""; }
348 $cr = wfMsg( "gnunote" );
349 $s .= "<p><em>{$rf}{$lm} {$cr}</em>\n";
350 return $s;
352 return $this->doAfterContent();
355 function doAfterContent()
357 global $wgUser, $wgOut, $wgLang;
358 $fname = "Skin::doAfterContent";
359 wfProfileIn( $fname );
360 wfProfileIn( "$fname-1" );
362 $s = "\n</div><br clear=all>\n";
363 $s .= "\n<div id='footer'>";
364 $s .= "<table width='98%' border=0 cellspacing=0><tr>";
366 wfProfileOut( "$fname-1" );
367 wfProfileIn( "$fname-2" );
369 $qb = $this->qbSetting();
370 $shove = ($qb != 0);
371 $left = ($qb == 1 || $qb == 3);
372 if($wgLang->isRTL()) $left = !$left;
374 if ( $shove && $left ) { # Left
375 $s .= $this->getQuickbarCompensator();
377 wfProfileOut( "$fname-2" );
378 wfProfileIn( "$fname-3" );
379 $l = $wgLang->isRTL() ? "right" : "left";
380 $s .= "<td class='bottom' align='$l' valign='top'>";
382 $s .= $this->bottomLinks();
383 $s .= "\n<br>" . $this->mainPageLink()
384 . " | " . $this->aboutLink()
385 . " | " . $this->specialLink( "recentchanges" )
386 . " | " . $this->searchForm()
387 . "<br>" . $this->pageStats();
389 $s .= "</td>";
390 if ( $shove && !$left ) { # Right
391 $s .= $this->getQuickbarCompensator();
393 $s .= "</tr></table>\n</div>\n</div>\n";
395 wfProfileOut( "$fname-3" );
396 wfProfileIn( "$fname-4" );
397 if ( 0 != $qb ) { $s .= $this->quickBar(); }
398 wfProfileOut( "$fname-4" );
399 wfProfileOut( $fname );
400 return $s;
403 function pageTitleLinks()
405 global $wgOut, $wgTitle, $oldid, $action, $diff, $wgUser, $wgLang, $wgUseApproval ;
407 $s = $this->printableLink();
409 if ( $wgOut->isArticle() ) {
410 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
411 $name = $wgTitle->getDBkey();
412 $link = wfEscapeHTML( wfImageUrl( $name ) );
413 $style = $this->getInternalLinkAttributes( $link, $name );
414 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
416 # This will show the "Approve" link if $wgUseApproval=true;
417 if ( isset ( $wgUseApproval ) && $wgUseApproval )
419 $t = $wgTitle->getDBkey();
420 $name = "Approve this article" ;
421 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
422 #wfEscapeHTML( wfImageUrl( $name ) );
423 $style = $this->getExternalLinkAttributes( $link, $name );
424 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
426 if ( "history" == $action || isset( $diff ) || isset( $oldid ) ) {
427 $s .= " | " . $this->makeKnownLink( $wgTitle->getPrefixedText(),
428 wfMsg( "currentrev" ) );
431 if ( $wgUser->getNewtalk() ) {
432 # do not show "You have new messages" text when we are viewing our
433 # own talk page
435 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
436 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
437 $n =$wgUser->getName();
438 $tl = $this->makeKnownLink( $wgLang->getNsText(
439 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
440 wfMsg("newmessageslink") );
441 $s.=" | <strong>". wfMsg( "newmessages", $tl ) . "</strong>";
444 if( $wgUser->isSysop() &&
445 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
446 ($n = $wgTitle->isDeleted() ) ) {
447 $s .= " | " . wfMsg( "thisisdeleted",
448 $this->makeKnownLink(
449 $wgLang->SpecialPage( "Undelete/" . $wgTitle->getPrefixedDBkey() ),
450 wfMsg( "restorelink", $n ) ) );
452 return $s;
455 function printableLink()
457 global $wgOut, $wgTitle, $oldid, $action;
459 $q = "";
460 foreach( $_GET as $var => $val ) {
461 if( $var != "title" && $var != "printable" )
462 $q .= urlencode( $var ) . "=" . urlencode( $val );
464 if( !empty( $q ) ) $q .= "&";
466 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
467 WfMsg( "printableversion" ), "{$q}printable=yes" );
468 return $s;
471 function pageTitle()
473 global $wgOut, $wgTitle, $wgUser;
475 $s = "<h1 class='pagetitle'>" . $wgOut->getPageTitle() . "</h1>";
476 if($wgUser->getOption("editsectiononrightclick") && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
477 return $s;
480 function pageSubtitle()
482 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
484 $sub = $wgOut->getSubtitle();
485 if ( "" == $sub ) {
486 global $wgExtraSubtitle;
487 $sub = wfMsg( "fromwikipedia" ) . $wgExtraSubtitle;
489 if($wgOut->isArticle() && $wgNamespacesWithSubpages[$wgTitle->getNamespace()]) {
490 $ptext=$wgTitle->getPrefixedText();
491 if(preg_match("/\//",$ptext)) {
492 $sub.="</p><p class='subpages'>";
493 $links=explode("/",$ptext);
494 $c=0;
495 $growinglink="";
496 foreach($links as $link) {
497 $c++;
498 if ($c<count($links)) {
499 $growinglink.=$link;
500 $getlink=$this->makeLink( $growingLink, $link);
501 if(preg_match("/class='new'/i",$getlink)) { break; } # this is a hack, but it saves time
502 if ($c>1) {
503 $sub .= " | ";
504 } else {
505 $sub .="&lt; ";
507 $sub .= $getlink;
508 $growinglink.="/";
514 $s = "<p class='subtitle'>{$sub}\n";
515 return $s;
518 function nameAndLogin()
520 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader;
522 $li = $wgLang->specialPage( "Userlogin" );
523 $lo = $wgLang->specialPage( "Userlogout" );
525 $s = "";
526 if ( 0 == $wgUser->getID() ) {
527 if( $wgShowIPinHeader ) {
528 $n = getenv( "REMOTE_ADDR" );
530 $tl = $this->makeKnownLink( $wgLang->getNsText(
531 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
532 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
534 $s .= $n . " (".$tl.")";
535 } else {
536 $s .= wfMsg("notloggedin");
539 $rt = $wgTitle->getPrefixedURL();
540 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
541 $q = "";
542 } else { $q = "returnto={$rt}"; }
544 $s .= "\n<br>" . $this->makeKnownLink( $li,
545 wfMsg( "login" ), $q );
546 } else {
547 $n = $wgUser->getName();
548 $rt = $wgTitle->getPrefixedURL();
549 $tl = $this->makeKnownLink( $wgLang->getNsText(
550 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
551 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
553 $tl = " ({$tl})";
555 $s .= $this->makeKnownLink( $wgLang->getNsText(
556 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br>" .
557 $this->makeKnownLink( $lo, wfMsg( "logout" ),
558 "returnto={$rt}" ) . " | " .
559 $this->specialLink( "preferences" );
561 $s .= " | " . $this->makeKnownLink( wfMsg( "helppage" ),
562 wfMsg( "help" ) );
564 return $s;
567 function searchForm()
569 global $search;
571 $s = "<form name='search' class='inline' method=get action=\""
572 . wfLocalUrl( "" ) . "\">"
573 . "<input type=text name=\"search\" size=19 value=\""
574 . htmlspecialchars(substr($search,0,256)) . "\">\n"
575 . "<input type=submit name=\"go\" value=\"" . wfMsg ("go") . "\">&nbsp;"
576 . "<input type=submit value=\"" . wfMsg ("search") . "\"></form>";
578 return $s;
581 function topLinks()
583 global $wgOut;
584 $sep = " |\n";
586 $s = $this->mainPageLink() . $sep
587 . $this->specialLink( "recentchanges" );
589 if ( $wgOut->isArticle() ) {
590 $s .= $sep . $this->editThisPage()
591 . $sep . $this->historyLink();
593 # Many people don't like this dropdown box
594 #$s .= $sep . $this->specialPagesList();
596 return $s;
599 function bottomLinks()
601 global $wgOut, $wgUser, $wgTitle;
602 $sep = " |\n";
604 $s = "";
605 if ( $wgOut->isArticle() ) {
606 $s .= "<strong>" . $this->editThisPage() . "</strong>";
607 if ( 0 != $wgUser->getID() ) {
608 $s .= $sep . $this->watchThisPage();
610 $s .= $sep . $this->talkLink()
611 . $sep . $this->historyLink()
612 . $sep . $this->whatLinksHere()
613 . $sep . $this->watchPageLinksLink();
615 if ( $wgTitle->getNamespace() == Namespace::getUser()
616 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
619 $id=User::idFromName($wgTitle->getText());
620 $ip=User::isIP($wgTitle->getText());
622 if($id || $ip) { # both anons and non-anons have contri list
623 $s .= $sep . $this->userContribsLink();
625 if ( 0 != $wgUser->getID() ) { # show only to signed in users
626 if($id) { # can only email non-anons
627 $s .= $sep . $this->emailUserLink();
631 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
632 $s .= "\n<br>" . $this->deleteThisPage() .
633 $sep . $this->protectThisPage() .
634 $sep . $this->moveThisPage();
636 $s .= "<br>\n" . $this->otherLanguages();
638 return $s;
641 function pageStats()
643 global $wgOut, $wgLang, $wgArticle;
644 global $oldid, $diff, $wgDisableCounters;
646 if ( ! $wgOut->isArticle() ) { return ""; }
647 if ( isset( $oldid ) || isset( $diff ) ) { return ""; }
648 if ( 0 == $wgArticle->getID() ) { return ""; }
650 if ( $wgDisableCounters ) {
651 $s = "";
652 } else {
653 $count = $wgArticle->getCount();
654 $s = wfMsg( "viewcount", $count );
656 $s .= $this->lastModified();
657 $s .= " " . wfMsg( "gnunote" );
658 return "<span id='pagestats'>{$s}</span>";
661 function lastModified()
663 global $wgLang, $wgArticle;
665 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
666 $s = " " . wfMsg( "lastmodified", $d );
667 return $s;
670 function logoText( $align = "" )
672 if ( "" != $align ) { $a = " align='{$align}'"; }
673 else { $a = ""; }
675 $mp = wfMsg( "mainpage" );
676 $s = "<a href=\"" . wfLocalUrlE( urlencode( $mp ) )
677 . "\"><img{$a} border=0 src=\""
678 . $this->getLogo() . "\" alt=\"" . "[{$mp}]\"></a>";
679 return $s;
682 function quickBar()
684 global $wgOut, $wgTitle, $wgUser, $action, $wgLang;
685 global $wpPreview;
686 $fname = "Skin::quickBar";
687 wfProfileIn( $fname );
689 $tns=$wgTitle->getNamespace();
691 $s = "\n<div id='quickbar'>";
692 $s .= "\n" . $this->logoText() . "\n<hr class='sep'>";
694 $sep = "\n<br>";
695 $s .= $this->mainPageLink()
696 . $sep . $this->specialLink( "recentchanges" )
697 . $sep . $this->specialLink( "randompage" );
698 if ($wgUser->getID()) {
699 $s.= $sep . $this->specialLink( "watchlist" ) ;
700 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
701 wfMsg( "mycontris" ), "target=" . wfUrlencode($wgUser->getName() ) );
704 // only show watchlist link if logged in
705 if ( wfMsg ( "currentevents" ) != "-" ) $s .= $sep . $this->makeKnownLink( wfMsg( "currentevents" ), "" ) ;
706 $s .= "\n<br><hr class='sep'>";
707 $articleExists = $wgTitle->getArticleId();
708 if ( $wgOut->isArticle() || $action =="edit" || $action =="history" || $wpPreview) {
709 if($wgOut->isArticle()) {
710 $s .= "<strong>" . $this->editThisPage() . "</strong>";
711 } else { # backlink to the article in edit or history mode
712 if($articleExists){ # no backlink if no article
713 switch($tns) {
714 case 0:
715 $text = wfMsg("articlepage");
716 break;
717 case 1:
718 $text = wfMsg("viewtalkpage");
719 break;
720 case 2:
721 $text = wfMsg("userpage");
722 break;
723 case 3:
724 $text = wfMsg("viewtalkpage");
725 break;
726 case 4:
727 $text = wfMsg("wikipediapage");
728 break;
729 case 5:
730 $text = wfMsg("viewtalkpage");
731 break;
732 case 6:
733 $text = wfMsg("imagepage");
734 break;
735 case 7:
736 $text = wfMsg("viewtalkpage");
737 break;
738 default:
739 $text= wfMsg("articlepage");
742 $link = $wgTitle->getText();
743 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
744 $link = $nstext . ":" . $link ;
747 $s .= $this->makeLink( $link, $text );
748 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
749 # we just throw in a "New page" text to tell the user that he's in edit mode,
750 # and to avoid messing with the separator that is prepended to the next item
751 $s .= "<strong>" . wfMsg("newpage") . "</strong>";
757 if( $tns%2 && $action!="edit" && !$wpPreview) {
758 $s.="<br>".$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("postcomment"),"action=edit&section=new");
762 watching could cause problems in edit mode:
763 if user edits article, then loads "watch this article" in background and then saves
764 article with "Watch this article" checkbox disabled, the article is transparently
765 unwatched. Therefore we do not show the "Watch this page" link in edit mode
767 if ( 0 != $wgUser->getID() && $articleExists) {
768 if($action!="edit" && $action!="history" &&
769 $action != "submit" )
771 $s .= $sep . $this->watchThisPage();
773 if ( $wgTitle->userCanEdit() )
774 $s .= $sep . $this->moveThisPage();
776 if ( $wgUser->isSysop() and $articleExists ) {
777 $s .= $sep . $this->deleteThisPage() .
778 $sep . $this->protectThisPage();
780 $s .= $sep . $this->talkLink();
781 if ($articleExists && $action !="history") {
782 $s .= $sep . $this->historyLink();
784 $s.=$sep . $this->whatLinksHere();
786 if($wgOut->isArticle()) {
787 $s .= $sep . $this->watchPageLinksLink();
790 if ( Namespace::getUser() == $wgTitle->getNamespace()
791 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
794 $id=User::idFromName($wgTitle->getText());
795 $ip=User::isIP($wgTitle->getText());
797 if($id||$ip) {
798 $s .= $sep . $this->userContribsLink();
800 if ( 0 != $wgUser->getID() ) {
801 if($id) { # can only email real users
802 $s .= $sep . $this->emailUserLink();
806 $s .= "\n<br><hr class='sep'>";
809 if ( 0 != $wgUser->getID() ) {
810 $s .= $this->specialLink( "upload" ) . $sep;
812 $s .= $this->specialLink( "specialpages" )
813 . $sep . $this->bugReportsLink();
815 global $wgSiteSupportPage;
816 if( $wgSiteSupportPage ) {
817 $s .= "\n<br><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
818 "\">" . wfMsg( "sitesupport" ) . "</a>";
821 $s .= "\n<br></div>\n";
822 wfProfileOut( $fname );
823 return $s;
826 function specialPagesList()
828 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
829 $a = array();
831 $validSP = $wgLang->getValidSpecialPages();
833 foreach ( $validSP as $name => $desc ) {
834 if ( "" == $desc ) { continue; }
835 $a[$name] = $desc;
837 if ( $wgUser->isSysop() )
839 $sysopSP = $wgLang->getSysopSpecialPages();
841 foreach ( $sysopSP as $name => $desc ) {
842 if ( "" == $desc ) { continue; }
843 $a[$name] = $desc ;
846 if ( $wgUser->isDeveloper() )
848 $devSP = $wgLang->getDeveloperSpecialPages();
850 foreach ( $devSP as $name => $desc ) {
851 if ( "" == $desc ) { continue; }
852 $a[$name] = $desc ;
855 $go = wfMsg( "go" );
856 $sp = wfMsg( "specialpages" );
857 $spp = $wgLang->specialPage( "Specialpages" );
859 $s = "<form id=\"specialpages\" method=\"get\" class=\"inline\" " .
860 "action=\"{$wgServer}{$wgRedirectScript}\">\n";
861 $s .= "<select name=\"wpDropdown\">\n";
862 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
864 foreach ( $a as $name => $desc ) {
865 $p = $wgLang->specialPage( $name );
866 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
868 $s .= "</select>\n";
869 $s .= "<input type=submit value=\"{$go}\" name=redirect>\n";
870 $s .= "</form>\n";
871 return $s;
874 function mainPageLink()
876 $mp = wfMsg( "mainpage" );
877 $s = $this->makeKnownLink( $mp, $mp );
878 return $s;
881 function copyrightLink()
883 $s = $this->makeKnownLink( wfMsg( "copyrightpage" ),
884 wfMsg( "copyrightpagename" ) );
885 return $s;
888 function aboutLink()
890 $s = $this->makeKnownLink( wfMsg( "aboutpage" ),
891 wfMsg( "aboutwikipedia" ) );
892 return $s;
895 function editThisPage()
897 global $wgOut, $wgTitle, $oldid, $redirect, $diff;
899 if ( ! $wgOut->isArticle() || $diff ) {
900 $s = wfMsg( "protectedpage" );
901 } else if ( $wgTitle->userCanEdit() ) {
902 $n = $wgTitle->getPrefixedText();
903 $t = wfMsg( "editthispage" );
904 $oid = $red = "";
906 if ( $redirect ) { $red = "&redirect={$redirect}"; }
907 if ( $oldid && ! isset( $diff ) ) {
908 $oid = "&oldid={$oldid}";
910 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
911 } else {
912 $s = wfMsg( "protectedpage" );
914 return $s;
917 function deleteThisPage()
919 global $wgUser, $wgOut, $wgTitle, $diff;
921 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
922 $n = $wgTitle->getPrefixedText();
923 $t = wfMsg( "deletethispage" );
925 $s = $this->makeKnownLink( $n, $t, "action=delete" );
926 } else {
927 $s = "";
929 return $s;
932 function protectThisPage()
934 global $wgUser, $wgOut, $wgTitle, $diff;
936 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
937 $n = $wgTitle->getPrefixedText();
939 if ( $wgTitle->isProtected() ) {
940 $t = wfMsg( "unprotectthispage" );
941 $q = "action=unprotect";
942 } else {
943 $t = wfMsg( "protectthispage" );
944 $q = "action=protect";
946 $s = $this->makeKnownLink( $n, $t, $q );
947 } else {
948 $s = "";
950 return $s;
953 function watchThisPage()
955 global $wgUser, $wgOut, $wgTitle, $diff;
957 if ( $wgOut->isArticle() && ( ! $diff ) ) {
958 $n = $wgTitle->getPrefixedText();
960 if ( $wgTitle->userIsWatching() ) {
961 $t = wfMsg( "unwatchthispage" );
962 $q = "action=unwatch";
963 } else {
964 $t = wfMsg( "watchthispage" );
965 $q = "action=watch";
967 $s = $this->makeKnownLink( $n, $t, $q );
968 } else {
969 $s = wfMsg( "notanarticle" );
971 return $s;
974 function moveThisPage()
976 global $wgTitle, $wgLang;
978 if ( $wgTitle->userCanEdit() ) {
979 $s = $this->makeKnownLink( $wgLang->specialPage( "Movepage" ),
980 wfMsg( "movethispage" ), "target=" . $wgTitle->getPrefixedURL() );
981 } // no message if page is protected - would be redundant
982 return $s;
985 function historyLink()
987 global $wgTitle;
989 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
990 wfMsg( "history" ), "action=history" );
991 return $s;
994 function whatLinksHere()
996 global $wgTitle, $wgLang;
998 $s = $this->makeKnownLink( $wgLang->specialPage( "Whatlinkshere" ),
999 wfMsg( "whatlinkshere" ), "target=" . $wgTitle->getPrefixedURL() );
1000 return $s;
1003 function userContribsLink()
1005 global $wgTitle, $wgLang;
1007 $s = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1008 wfMsg( "contributions" ), "target=" . $wgTitle->getURL() );
1009 return $s;
1012 function emailUserLink()
1014 global $wgTitle, $wgLang;
1016 $s = $this->makeKnownLink( $wgLang->specialPage( "Emailuser" ),
1017 wfMsg( "emailuser" ), "target=" . $wgTitle->getURL() );
1018 return $s;
1021 function watchPageLinksLink()
1023 global $wgOut, $wgTitle, $wgLang;
1025 if ( ! $wgOut->isArticle() ) {
1026 $s = "(" . wfMsg( "notanarticle" ) . ")";
1027 } else {
1028 $s = $this->makeKnownLink( $wgLang->specialPage(
1029 "Recentchangeslinked" ), wfMsg( "recentchangeslinked" ),
1030 "target=" . $wgTitle->getPrefixedURL() );
1032 return $s;
1035 function otherLanguages()
1037 global $wgOut, $wgLang, $wgTitle;
1039 $a = $wgOut->getLanguageLinks();
1040 # TEST THIS @@@
1041 if ( 0 == count( $a ) ) {
1042 if ( !$wgUseNewInterlanguage ) return "";
1043 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1044 if ( $ns != 0 AND $ns != 1 ) return "" ;
1045 $pn = "Intl" ;
1046 $x = "mode=addlink&xt=".$wgTitle->getDBkey() ;
1047 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1048 wfMsg( "intl" ) , $x );
1051 if ( !$wgUseNewInterlanguage ) {
1052 $s = wfMsg( "otherlanguages" ) . ": ";
1053 } else {
1054 global $wgLanguageCode ;
1055 $x = "mode=zoom&xt=".$wgTitle->getDBkey() ;
1056 $x .= "&xl=".$wgLanguageCode ;
1057 $s = $this->makeKnownLink( $wgLang->specialPage( "Intl" ),
1058 wfMsg( "otherlanguages" ) , $x ) . ": " ;
1061 $s = wfMsg( "otherlanguages" ) . ": ";
1062 $first = true;
1063 if($wgLang->isRTL()) $s .= "<span dir='LTR'>";
1064 foreach( $a as $l ) {
1065 if ( ! $first ) { $s .= " | "; }
1066 $first = false;
1068 $nt = Title::newFromText( $l );
1069 $url = $nt->getFullURL();
1070 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1072 if ( "" == $text ) { $text = $l; }
1073 $style = $this->getExternalLinkAttributes( $l, $text );
1074 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1076 if($wgLang->isRTL()) $s .= "</span>";
1077 return $s;
1080 function bugReportsLink()
1082 $s = $this->makeKnownLink( wfMsg( "bugreportspage" ),
1083 wfMsg( "bugreports" ) );
1084 return $s;
1087 function dateLink()
1089 global $wgLinkCache;
1090 $t1 = Title::newFromText( gmdate( "F j" ) );
1091 $t2 = Title::newFromText( gmdate( "Y" ) );
1093 $wgLinkCache->suspend();
1094 $id = $t1->getArticleID();
1095 $wgLinkCache->resume();
1097 if ( 0 == $id ) {
1098 $s = $this->makeBrokenLink( $t1->getText() );
1099 } else {
1100 $s = $this->makeKnownLink( $t1->getText() );
1102 $s .= ", ";
1104 $wgLinkCache->suspend();
1105 $id = $t2->getArticleID();
1106 $wgLinkCache->resume();
1108 if ( 0 == $id ) {
1109 $s .= $this->makeBrokenLink( $t2->getText() );
1110 } else {
1111 $s .= $this->makeKnownLink( $t2->getText() );
1113 return $s;
1116 function talkLink()
1118 global $wgLang, $wgTitle, $wgLinkCache;
1120 $tns = $wgTitle->getNamespace();
1121 if ( -1 == $tns ) { return ""; }
1123 $pn = $wgTitle->getText();
1124 $tp = wfMsg( "talkpage" );
1125 if ( Namespace::isTalk( $tns ) ) {
1126 $lns = Namespace::getSubject( $tns );
1127 switch($tns) {
1128 case 1:
1129 $text = wfMsg("articlepage");
1130 break;
1131 case 3:
1132 $text = wfMsg("userpage");
1133 break;
1134 case 5:
1135 $text = wfMsg("wikipediapage");
1136 break;
1137 case 7:
1138 $text = wfMsg("imagepage");
1139 break;
1140 default:
1141 $text= wfMsg("articlepage");
1143 } else {
1145 $lns = Namespace::getTalk( $tns );
1146 $text=$tp;
1148 $n = $wgLang->getNsText( $lns );
1149 if ( "" == $n ) { $link = $pn; }
1150 else { $link = "{$n}:{$pn}"; }
1152 $wgLinkCache->suspend();
1153 $s = $this->makeLink( $link, $text );
1154 $wgLinkCache->resume();
1156 return $s;
1159 function commentLink()
1161 global $wgLang, $wgTitle, $wgLinkCache;
1163 $tns = $wgTitle->getNamespace();
1164 if ( -1 == $tns ) { return ""; }
1166 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1168 # assert Namespace::isTalk( $lns )
1170 $n = $wgLang->getNsText( $lns );
1171 $pn = $wgTitle->getText();
1173 $link = "{$n}:{$pn}";
1175 $wgLinkCache->suspend();
1176 $s = $this->makeKnownLink($link, wfMsg("postcomment"), "action=edit&section=new");
1177 $wgLinkCache->resume();
1179 return $s;
1182 # After all the page content is transformed into HTML, it makes
1183 # a final pass through here for things like table backgrounds.
1185 function transformContent( $text )
1187 return $text;
1190 # Note: This function MUST call getArticleID() on the link,
1191 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1193 function makeLink( $title, $text = "", $query = "", $trail = "" ) {
1194 wfProfileIn( "Skin::makeLink" );
1195 $nt = Title::newFromText( $title );
1196 if ($nt) {
1197 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1198 } else {
1199 $result = $text == "" ? $title : $text;
1202 wfProfileOut( "Skin::makeLink" );
1203 return $result;
1206 function makeKnownLink( $title, $text = "", $query = "", $trail = "" ) {
1207 $nt = Title::newFromText( $title );
1208 if ($nt) {
1209 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1210 } else {
1211 return $text == "" ? $title : $text;
1215 function makeBrokenLink( $title, $text = "", $query = "", $trail = "" ) {
1216 $nt = Title::newFromText( $title );
1217 if ($nt) {
1218 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1219 } else {
1220 return $text == "" ? $title : $text;
1224 function makeStubLink( $title, $text = "", $query = "", $trail = "" ) {
1225 $nt = Title::newFromText( $title );
1226 if ($nt) {
1227 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1228 } else {
1229 return $text == "" ? $title : $text;
1233 # Pass a title object, not a title string
1234 function makeLinkObj( &$nt, $text= "", $query = "", $trail = "" )
1236 global $wgOut, $wgUser;
1237 if ( $nt->isExternal() ) {
1238 $u = $nt->getFullURL();
1239 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1240 $style = $this->getExternalLinkAttributes( $link, $text );
1242 $inside = "";
1243 if ( "" != $trail ) {
1244 if ( preg_match( "/^([a-z]+)(.*)$$/sD", $trail, $m ) ) {
1245 $inside = $m[1];
1246 $trail = $m[2];
1249 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1250 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1251 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
1252 } elseif ( ( -1 == $nt->getNamespace() ) ||
1253 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1254 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
1255 } else {
1256 $aid = $nt->getArticleID() ;
1257 if ( 0 == $aid ) {
1258 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail );
1259 } else {
1260 $threshold = $wgUser->getOption("stubthreshold") ;
1261 if ( $threshold > 0 ) {
1262 $res = wfQuery ( "SELECT HIGH_PRIORITY length(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ ) ;
1264 if ( wfNumRows( $res ) > 0 ) {
1265 $s = wfFetchObject( $res );
1266 $size = $s->x;
1267 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1268 $size = $threshold*2 ; # Really big
1270 wfFreeResult( $res );
1271 } else {
1272 $size = $threshold*2 ; # Really big
1274 } else {
1275 $size = 1 ;
1277 if ( $size < $threshold ) {
1278 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail );
1279 } else {
1280 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
1284 return $retVal;
1287 # Pass a title object, not a title string
1288 function makeKnownLinkObj( &$nt, $text = "", $query = "", $trail = "" )
1290 global $wgOut, $wgTitle;
1292 $fname = "Skin::makeKnownLinkObj";
1293 wfProfileIn( $fname );
1295 $link = $nt->getPrefixedURL();
1297 if ( "" == $link ) {
1298 $u = "";
1299 if ( "" == $text ) { $text = $nt->getFragment(); }
1300 } else {
1301 $u = wfLocalUrlE( $link, $query );
1303 if ( "" != $nt->getFragment() ) {
1304 $u .= "#" . wfEscapeHTML( $nt->getFragment() );
1306 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1307 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1309 $inside = "";
1310 if ( "" != $trail ) {
1311 if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
1312 $inside = $m[1];
1313 $trail = $m[2];
1316 $r = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1317 wfProfileOut( $fname );
1318 return $r;
1321 # Pass a title object, not a title string
1322 function makeBrokenLinkObj( &$nt, $text = "", $query = "", $trail = "" )
1324 global $wgOut, $wgUser;
1326 $fname = "Skin::makeBrokenLinkObj";
1327 wfProfileIn( $fname );
1329 $link = $nt->getPrefixedURL();
1331 if ( "" == $query ) { $q = "action=edit"; }
1332 else { $q = "action=edit&{$query}"; }
1333 $u = wfLocalUrlE( $link, $q );
1335 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1336 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1338 $inside = "";
1339 if ( "" != $trail ) {
1340 if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
1341 $inside = $m[1];
1342 $trail = $m[2];
1345 if ( $wgOut->isPrintable() ||
1346 ( 1 == $wgUser->getOption( "highlightbroken" ) ) ) {
1347 $s = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1348 } else {
1349 $s = "{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1352 wfProfileOut( $fname );
1353 return $s;
1356 # Pass a title object, not a title string
1357 function makeStubLinkObj( &$nt, $text = "", $query = "", $trail = "" )
1359 global $wgOut, $wgUser;
1361 $link = $nt->getPrefixedURL();
1363 $u = wfLocalUrlE( $link, $query );
1365 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1366 $style = $this->getInternalLinkAttributesObj( $nt, $text, "stub" );
1368 $inside = "";
1369 if ( "" != $trail ) {
1370 if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
1371 $inside = $m[1];
1372 $trail = $m[2];
1375 if ( $wgOut->isPrintable() ||
1376 ( 1 == $wgUser->getOption( "highlightbroken" ) ) ) {
1377 $s = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1378 } else {
1379 $s = "{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1381 return $s;
1384 function fnamePart( $url )
1386 $basename = strrchr( $url, "/" );
1387 if ( false === $basename ) { $basename = $url; }
1388 else { $basename = substr( $basename, 1 ); }
1389 return wfEscapeHTML( $basename );
1392 function makeImage( $url, $alt = "" )
1394 global $wgOut;
1396 if ( "" == $alt ) { $alt = $this->fnamePart( $url ); }
1397 $s = "<img src=\"{$url}\" alt=\"{$alt}\">";
1398 return $s;
1401 function makeImageLink( $name, $url, $alt = "" ) {
1402 $nt = Title::makeTitle( Namespace::getImage(), $name );
1403 return $this->makeImageLinkObj( $nt, $alt );
1406 function makeImageLinkObj( $nt, $alt = "" ) {
1407 $link = $nt->getPrefixedURL();
1408 $name = $nt->getDBKey();
1409 $url = wfImageUrl( $name );
1410 if ( empty( $alt ) ) {
1411 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1413 $alt = htmlspecialchars( $alt );
1415 $u = wfLocalUrlE( $link );
1416 $s = "<a href=\"{$u}\" class='image' title=\"{$alt}\">" .
1417 "<img border=\"0\" src=\"{$url}\" alt=\"{$alt}\"></a>";
1418 return $s;
1421 function makeMediaLink( $name, $url, $alt = "" ) {
1422 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1423 return $this->makeMediaLinkObj( $nt, $alt );
1426 function makeMediaLinkObj( $nt, $alt = "" )
1428 $name = $nt->getDBKey();
1429 $url = wfImageUrl( $name );
1430 if ( empty( $alt ) ) {
1431 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1434 $u = htmlspecialchars( $url );
1435 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1436 return $s;
1439 function specialLink( $name, $key = "" )
1441 global $wgLang;
1443 if ( "" == $key ) { $key = strtolower( $name ); }
1444 $pn = $wgLang->ucfirst( $name );
1445 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1446 wfMsg( $key ) );
1449 # Called by history lists and recent changes
1452 function beginRecentChangesList()
1454 $rc_cache = array() ;
1455 $rccc = 0 ;
1456 $this->lastdate = "";
1457 return "";
1460 function beginHistoryList()
1462 $this->lastdate = $this->lastline = "";
1463 $s = "\n<p>" . wfMsg( "histlegend" ) . "\n<ul>";
1464 return $s;
1467 function beginImageHistoryList()
1469 $s = "\n<h2>" . wfMsg( "imghistory" ) . "</h2>\n" .
1470 "<p>" . wfMsg( "imghistlegend" ) . "\n<ul>";
1471 return $s;
1474 function endRecentChangesList()
1476 $s = $this->recentChangesBlock() ;
1477 $s .= "</ul>\n";
1478 return $s;
1481 function endHistoryList()
1483 $last = wfMsg( "last" );
1485 $s = preg_replace( "/!OLDID![0-9]+!/", $last, $this->lastline );
1486 $s .= "</ul>\n";
1487 return $s;
1490 function endImageHistoryList()
1492 $s = "</ul>\n";
1493 return $s;
1496 function historyLine( $ts, $u, $ut, $ns, $ttl, $oid, $c, $isminor )
1498 global $wgLang;
1500 $artname = Title::makeName( $ns, $ttl );
1501 $last = wfMsg( "last" );
1502 $cur = wfMsg( "cur" );
1503 $cr = wfMsg( "currentrev" );
1505 if ( $oid && $this->lastline ) {
1506 $ret = preg_replace( "/!OLDID!([0-9]+)!/", $this->makeKnownLink(
1507 $artname, $last, "diff=\\1&oldid={$oid}" ), $this->lastline );
1508 } else {
1509 $ret = "";
1511 $dt = $wgLang->timeanddate( $ts, true );
1513 if ( $oid ) { $q = "oldid={$oid}"; }
1514 else { $q = ""; }
1515 $link = $this->makeKnownLink( $artname, $dt, $q );
1517 if ( 0 == $u ) {
1518 $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1519 $ut, "target=" . $ut );
1520 } else {
1521 $ul = $this->makeLink( $wgLang->getNsText(
1522 Namespace::getUser() ) . ":{$ut}", $ut ); }
1524 $s = "<li>";
1525 if ( $oid ) {
1526 $curlink = $this->makeKnownLink( $artname, $cur,
1527 "diff=0&oldid={$oid}" );
1528 } else {
1529 $curlink = $cur;
1531 $s .= "({$curlink}) (!OLDID!{$oid}!) . .";
1533 $M = wfMsg( "minoreditletter" );
1534 if ( $isminor ) { $s .= " <strong>{$M}</strong>"; }
1535 $s .= " {$link} . . {$ul}";
1537 if ( "" != $c && "*" != $c ) { $s .= " <em>(" . wfEscapeHTML($c) . ")</em>"; }
1538 $s .= "</li>\n";
1540 $this->lastline = $s;
1541 return $ret;
1544 function recentChangesBlockLine ( $y ) {
1545 global $wgUploadPath ;
1547 $M = wfMsg( "minoreditletter" );
1548 $N = wfMsg( "newpageletter" );
1549 $r = "" ;
1550 $r .= "<img src='{$wgUploadPath}/Arr_.png' width=12 height=12 border=0>" ;
1551 $r .= "<tt>" ;
1552 if ( $y->isnew ) $r .= $N ;
1553 else $r .= "&nbsp;" ;
1554 if ( $y->isminor ) $r .= $M ;
1555 else $r .= "&nbsp;" ;
1556 $r .= " ".$y->timestamp." " ;
1557 $r .= "</tt>" ;
1558 $link = $y->link ;
1559 if ( $y->watched ) $link = "<strong>{$link}</strong>" ;
1560 $r .= $link ;
1562 $r .= " (" ;
1563 $r .= $y->curlink ;
1564 $r .= "; " ;
1565 $r .= $this->makeKnownLink( $y->secureName, wfMsg( "hist" ), "action=history" );
1567 $r .= ") . . ".$y->userlink ;
1568 $r .= $y->usertalklink ;
1569 if ( $y->usercomment != "" )
1570 $r .= " <em>(".wfEscapeHTML($y->usercomment).")</em>" ;
1571 $r .= "<br>\n" ;
1572 return $r ;
1575 function recentChangesBlockGroup ( $y ) {
1576 global $wgUploadPath ;
1578 $r = "" ;
1579 $M = wfMsg( "minoreditletter" );
1580 $N = wfMsg( "newpageletter" );
1581 $isnew = false ;
1582 $userlinks = array () ;
1583 foreach ( $y AS $x ) {
1584 $oldid = $x->diffid ;
1585 if ( $x->isnew ) $isnew = true ;
1586 $u = $x->userlink ;
1587 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
1588 $userlinks[$u]++ ;
1591 krsort ( $userlinks ) ;
1592 asort ( $userlinks ) ;
1593 $users = array () ;
1594 $u = array_keys ( $userlinks ) ;
1595 foreach ( $u as $x ) {
1596 $z = $x ;
1597 if ( $userlinks[$x] > 1 ) $z .= " ({$userlinks[$x]}&times;)" ;
1598 array_push ( $users , $z ) ;
1600 $users = " <font size='-1'>[".implode("; ",$users)."]</font>" ;
1602 $e = $y ;
1603 $e = array_shift ( $e ) ;
1605 # Arrow
1606 $rci = "RCI{$this->rccc}" ;
1607 $rcl = "RCL{$this->rccc}" ;
1608 $rcm = "RCM{$this->rccc}" ;
1609 $tl = "<a href='javascript:toggleVisibility(\"{$rci}\",\"{$rcm}\",\"{$rcl}\")'>" ;
1610 $tl .= "<span id='{$rcm}'><img src='{$wgUploadPath}/Arr_r.png' width=12 height=12 border=0></span>" ;
1611 $tl .= "<span id='{$rcl}' style='display:none'><img src='{$wgUploadPath}/Arr_d.png' width=12 height=12 border=0></span>" ;
1612 $tl .= "</a>" ;
1613 $r .= $tl ;
1615 # Main line
1616 $r .= "<tt>" ;
1617 if ( $isnew ) $r .= $N ;
1618 else $r .= "&nbsp;" ;
1619 $r .= "&nbsp;" ; # Minor
1620 $r .= " ".$e->timestamp." " ;
1621 $r .= "</tt>" ;
1623 $link = $e->link ;
1624 if ( $e->watched ) $link = "<strong>{$link}</strong>" ;
1625 $r .= $link ;
1627 if ( !$e->islog ) {
1628 $r .= " (".count($y)." " ;
1629 if ( $isnew ) $r .= wfMsg("changes");
1630 else $r .= $this->makeKnownLink( $e->secureName , wfMsg("changes") , "diff=0&oldid=".$oldid ) ;
1631 $r .= "; " ;
1632 $r .= $this->makeKnownLink( $e->secureName, wfMsg( "history" ), "action=history" );
1633 $r .= ")" ;
1636 $r .= $users ;
1637 $r .= "<br>\n" ;
1639 # Sub-entries
1640 $r .= "<div id='{$rci}' style='display:none'>" ;
1641 foreach ( $y AS $x )
1643 $r .= "<img src='{$wgUploadPath}/Arr_.png' width=12 height=12 border=0>";
1644 $r .= "<tt>&nbsp; &nbsp; &nbsp; &nbsp;" ;
1645 if ( $x->isnew ) $r .= $N ;
1646 else $r .= "&nbsp;" ;
1647 if ( $x->isminor ) $r .= $M ;
1648 else $r .= "&nbsp;" ;
1649 $r .= "</tt>" ;
1651 $o = "" ;
1652 if ( $x->oldid != 0 ) $o = "oldid=".$x->oldid ;
1653 if ( $x->islog ) $link = $x->timestamp ;
1654 else $link = $this->makeKnownLink( $x->secureName, $x->timestamp , $o ) ;
1655 $link = "<tt>{$link}</tt>" ;
1658 $r .= $link ;
1659 $r .= " (" ;
1660 $r .= $x->curlink ;
1661 $r .= "; " ;
1662 $r .= $x->lastlink ;
1663 $r .= ") . . ".$x->userlink ;
1664 $r .= $x->usertalklink ;
1665 if ( $x->usercomment != "" )
1666 $r .= " <em>(".wfEscapeHTML($x->usercomment).")</em>" ;
1667 $r .= "<br>\n" ;
1669 $r .= "</div>\n" ;
1671 $this->rccc++ ;
1672 return $r ;
1675 function recentChangesBlock ()
1677 global $wgUploadPath ;
1678 if ( count ( $this->rc_cache ) == 0 ) return "" ;
1679 $k = array_keys ( $this->rc_cache ) ;
1680 foreach ( $k AS $x )
1682 $y = $this->rc_cache[$x] ;
1683 if ( count ( $y ) < 2 ) {
1684 $r .= $this->recentChangesBlockLine ( array_shift ( $y ) ) ;
1685 } else {
1686 $r .= $this->recentChangesBlockGroup ( $y ) ;
1690 return "<div align=left>{$r}</div>" ;
1693 function recentChangesLine( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
1695 global $wgUser ;
1696 $usenew = $wgUser->getOption( "usenewrc" );
1697 if ( $usenew )
1698 $r = $this->recentChangesLineNew ( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched , $oldid , $diffid ) ;
1699 else
1700 $r = $this->recentChangesLineOld ( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched , $oldid , $diffid ) ;
1701 return $r ;
1704 function recentChangesLineOld( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0, $diffid = 0 )
1706 global $wgTitle, $wgLang, $wgUser;
1708 $d = $wgLang->date( $ts, true);
1709 $s = "";
1710 if ( $d != $this->lastdate ) {
1711 if ( "" != $this->lastdate ) { $s .= "</ul>\n"; }
1712 $s .= "<h4>{$d}</h4>\n<ul>";
1713 $this->lastdate = $d;
1715 $h = $wgLang->time( $ts, true );
1716 $t = Title::makeName( $ns, $ttl );
1717 $clink = $this->makeKnownLink( $t , "" );
1718 $nt = Title::newFromText( $t );
1720 if ( $watched ) {
1721 $clink = "<strong>{$clink}</strong>";
1723 $hlink = $this->makeKnownLink( $t, wfMsg( "hist" ), "action=history" );
1724 if ( $isnew || $nt->isLog() ) {
1725 $dlink = wfMsg( "diff" );
1726 } else {
1727 $dlink = $this->makeKnownLink( $t, wfMsg( "diff" ),
1728 "diff={$oldid}&oldid={$diffid}" ); # Finagle's law
1730 if ( 0 == $u ) {
1731 $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1732 $ut, "target=" . $ut );
1733 } else {
1734 $ul = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) . ":{$ut}", $ut );
1737 $talkname=$wgLang->getNsText(Namespace::getTalk(0)); # use the shorter name
1738 global $wgDisableAnonTalk;
1739 if( 0 == $u && $wgDisableAnonTalk ) {
1740 $utl = "";
1741 } else {
1742 $utns=$wgLang->getNsText(Namespace::getTalk(Namespace::getUser()));
1743 $utl= $this->makeLink($utns . ":{$ut}", $talkname );
1745 $cr = wfMsg( "currentrev" );
1747 $s .= "<li> ({$dlink}) ({$hlink}) . .";
1748 $M = wfMsg( "minoreditletter" );
1749 $N = wfMsg( "newpageletter" );
1750 if ( $isminor ) { $s .= " <strong>{$M}</strong>"; }
1751 if ( $isnew ) { $s .= "<strong>{$N}</strong>"; }
1752 $s .= " {$clink}; {$h} . . {$ul}";
1754 $blink="";
1755 if ( ( 0 == $u ) && $wgUser->isSysop() ) {
1756 $blink = $this->makeKnownLink( $wgLang->specialPage(
1757 "Blockip" ), wfMsg( "blocklink" ), "ip={$ut}" );
1760 if($blink) {
1761 if($utl) $utl .= " | ";
1762 $utl .= $blink;
1764 if($utl) $s.=" ({$utl})";
1766 if ( "" != $c && "*" != $c ) {
1767 $s .= " <em>(" . wfEscapeHTML( $c ) . ")</em>";
1769 $s .= "</li>\n";
1771 return $s;
1774 function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
1776 global $wgTitle, $wgLang, $wgUser;
1778 $rc = new RecentChangesClass ;
1780 $d = $wgLang->date( $ts, true);
1781 $s = "";
1782 $ret = "" ;
1783 if ( $d != $this->lastdate ) {
1784 $ret = $this->recentChangesBlock () ;
1785 $this->rc_cache = array() ;
1786 $ret .= "<h4>{$d}</h4>\n";
1787 $this->lastdate = $d;
1789 $h = $wgLang->time( $ts, true );
1790 $t = Title::makeName( $ns, $ttl );
1791 $clink = $this->makeKnownLink( $t, "" ) ;
1792 if ( $oldid == 0 ) $c2link = $clink ;
1793 else $c2link = $this->makeKnownLink( $t, "" , "oldid={$oldid}" );
1794 $nt = Title::newFromText( $t );
1796 $rc->timestamp = $h ;
1797 $rc->oldid = $oldid ;
1798 $rc->diffid = $diffid ;
1799 $rc->watched = $watched ;
1800 $rc->isnew = $isnew ;
1801 $rc->isminor = $isminor ;
1802 $rc->secureName = $t ;
1803 $rc->displayName = $nt ;
1804 $rc->link = $clink ;
1805 $rc->usercomment = $c ;
1806 $rc->islog = $nt->isLog() ;
1808 if ( ( $isnew && $oldid == 0 ) || $nt->isLog() ) {
1809 $dlink = wfMsg( "cur" );
1810 } else {
1811 $dlink = $this->makeKnownLink( $t, wfMsg( "cur" ),
1812 "diff=0&oldid={$oldid}" );
1815 if ( $diffid == 0 || $nt->isLog() ) {
1816 $plink = wfMsg( "last" );
1817 } else {
1818 $plink = $this->makeKnownLink( $t, wfMsg( "last" ),
1819 "diff={$oldid}&oldid={$diffid}" );
1822 if ( 0 == $u ) {
1823 $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1824 $ut, "target=" . $ut );
1825 } else { $ul = $this->makeLink( $wgLang->getNsText(
1826 Namespace::getUser() ) . ":{$ut}", $ut ); }
1828 $rc->userlink = $ul ;
1829 $rc->lastlink = $plink ;
1830 $rc->curlink = $dlink ;
1832 $utns=$wgLang->getNsText(Namespace::getTalk(Namespace::getUser()));
1833 $talkname=$wgLang->getNsText(Namespace::getTalk(0)); # use the shorter name
1834 $utl= $this->makeLink($utns . ":{$ut}", $talkname );
1836 global $wgDisableAnonTalk;
1837 if ( ( 0 == $u ) && $wgUser->isSysop() ) {
1838 $blink = $this->makeKnownLink( $wgLang->specialPage(
1839 "Blockip" ), wfMsg( "blocklink" ), "ip={$ut}" );
1840 if( $wgDisableAnonTalk )
1841 $rc->usertalklink = " ({$blink})";
1842 else
1843 $rc->usertalklink = " ({$utl} | {$blink})";
1844 } else {
1845 if( $wgDisableAnonTalk && ($u == 0) )
1846 $rc->usertalklink = "";
1847 else
1848 $rc->usertalklink = " ({$utl})";
1851 if ( !isset ( $this->rc_cache[$t] ) ) $this->rc_cache[$t] = array() ;
1852 array_push ( $this->rc_cache[$t] , $rc ) ;
1853 return $ret;
1857 function imageHistoryLine( $iscur, $ts, $img, $u, $ut, $size, $c )
1859 global $wgUser, $wgLang, $wgTitle;
1861 $dt = $wgLang->timeanddate( $ts, true );
1862 $del = wfMsg( "deleteimg" );
1863 $cur = wfMsg( "cur" );
1865 if ( $iscur ) {
1866 $url = wfImageUrl( $img );
1867 $rlink = $cur;
1868 if ( $wgUser->isSysop() ) {
1869 $link = wfLocalUrlE( $wgTitle->getPrefixedText(), "image=" . $wgTitle->getURL() .
1870 "&action=delete" );
1871 $style = $this->getInternalLinkAttributes( $link, $del );
1873 $dlink = "<a href=\"{$link}\"{$style}>{$del}</a>";
1874 } else {
1875 $dlink = $del;
1877 } else {
1878 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
1879 if( $wgUser->getID() != 0 ) {
1880 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1881 wfMsg( "revertimg" ), "action=revert&oldimage=" .
1882 urlencode( $img ) );
1883 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1884 $del, "action=delete&oldimage=" . urlencode( $img ) );
1885 } else {
1886 # Having live active links for non-logged in users
1887 # means that bots and spiders crawling our site can
1888 # inadvertently change content. Baaaad idea.
1889 $rlink = wfMsg( "revertimg" );
1890 $dlink = $del;
1893 if ( 0 == $u ) { $ul = $ut; }
1894 else { $ul = $this->makeLink( $wgLang->getNsText(
1895 Namespace::getUser() ) . ":{$ut}", $ut ); }
1897 $nb = wfMsg( "nbytes", $size );
1898 $style = $this->getInternalLinkAttributes( $url, $dt );
1900 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$dt}</a>"
1901 . " . . {$ul} ({$nb})";
1903 if ( "" != $c && "*" != $c ) {
1904 $s .= " <em>(" . wfEscapeHTML( $c ) . ")</em>";
1906 $s .= "</li>\n";
1907 return $s;
1910 function tocIndent($level) {
1912 while($level-->0) $rv.="<div style=\"margin-left:2em;\">\n";
1913 return $rv;
1917 function tocUnindent($level) {
1918 while($level-->0) $rv.="</div>\n";
1919 return $rv;
1922 // parameter level defines if we are on an indentation level
1923 function tocLine($anchor,$tocline,$level) {
1925 if($level) {
1927 return "<A CLASS=\"internal\" HREF=\"#".$anchor."\">".$tocline."</A><BR>\n";
1928 } else {
1930 return "<div style=\"margin-bottom:0px;\">\n".
1931 "<A CLASS=\"internal\" HREF=\"#".$anchor."\">".$tocline."</A><BR>\n".
1932 "</div>\n";
1937 function tocTable($toc) {
1938 // note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
1939 global $printable;
1941 if (!$printable) {
1942 $hideline = " <script type='text/javascript'>showTocToggle(\"" . wfMsg("showtoc") . "\",\"" . wfMsg("hidetoc") . "\")</script>";
1944 return
1945 "<p><table border=\"0\" id=\"toc\"><tr><td align=\"center\">\n".
1946 "<b>".wfMsg("toc")."</b>" .
1947 $hideline .
1948 "</td></tr><tr id='tocinside'><td align=\"left\">\n".
1949 $toc."</td></tr></table><P>\n";
1952 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
1953 function editSectionScript($section,$head) {
1955 global $wgTitle,$wgUser,$oldid;
1956 if($oldid) return $head;
1957 $url = wfLocalUrlE(urlencode($wgTitle->getPrefixedText()),"action=edit&section=$section");
1958 return "<span onContextMenu='document.location=\"".$url."\";return false;'>{$head}</span>";
1961 function editSectionLink($section) {
1963 global $printable;
1964 global $wgTitle,$wgUser,$oldid;
1965 if($oldid) return "";
1966 if ($printable) return "";
1967 $editurl="&section={$section}";
1968 $url=$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("editsection"),"action=edit".$editurl);
1969 return "<div style=\"float:right;margin-left:5px;\"><small>[".$url."]</small></div>";
1974 include_once( "SkinStandard.php" );
1975 include_once( "SkinNostalgia.php" );
1976 include_once( "SkinCologneBlue.php" );
1978 #include_once( "SkinSmarty.php" );