fixed section anchors
[mediawiki.git] / includes / Skin.php
blob2836a244dad98e5cd125469ae7c2acc176a041c4
1 <?php
3 include_once( "Feed.php" );
5 # See skin.doc
7 # These are the INTERNAL names, which get mapped
8 # directly to class names. For display purposes, the
9 # Language class has internationalized names
11 /* private */ $wgValidSkinNames = array(
12 "Standard", "Nostalgia", "CologneBlue"
14 if( $wgUseSmarty ) {
15 $wgValidSkinNames[] = "Smarty";
16 $wgValidSkinNames[] = "Montparnasse";
18 if( $wgUsePHPTal ) {
19 #$wgValidSkinNames[] = "PHPTal";
20 $wgValidSkinNames[] = "DaVinci";
23 include_once( "RecentChange.php" );
25 # For some odd PHP bug, this function can't be part of a class
26 function getCategories ()
28 global $wgOut , $wgTitle , $wgUseCategoryMagic , $wgUser , $wgParser ;
29 if ( !isset ( $wgUseCategoryMagic ) || !$wgUseCategoryMagic ) return "" ;
30 if ( count ( $wgParser->mCategoryLinks ) == 0 ) return "" ;
31 if ( !$wgOut->isArticle() ) return "" ;
32 $sk = $wgUser->getSkin() ;
33 $s = "" ;
34 $s .= "\n<br>\n";
35 $s .= $sk->makeKnownLink ( "Special:Categories" , "Categories" , "article=".$wgTitle->getDBkey() ) ;
36 $t = implode ( " | " , $wgParser->mCategoryLinks ) ;
37 if ( $t != "" ) $s .= " : " ;
38 $s .= $t ;
39 return $s ;
42 class RCCacheEntry extends RecentChange
44 var $secureName, $link;
45 var $curlink , $lastlink , $usertalklink , $versionlink ;
46 var $userlink, $timestamp, $watched;
48 function newFromParent( $rc )
50 $rc2 = new RCCacheEntry;
51 $rc2->mAttribs = $rc->mAttribs;
52 $rc2->mExtra = $rc->mExtra;
53 return $rc2;
55 } ;
57 class Skin {
59 /* private */ var $lastdate, $lastline;
60 var $linktrail ; # linktrail regexp
61 var $rc_cache ; # Cache for Enhanced Recent Changes
62 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
63 var $rcMoveIndex;
65 function Skin()
67 $this->linktrail = wfMsg("linktrail");
70 function getSkinNames()
72 global $wgValidSkinNames;
73 return $wgValidSkinNames;
76 function getStylesheet()
78 return "wikistandard.css";
81 function qbSetting()
83 global $wgOut, $wgUser;
85 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
86 $q = $wgUser->getOption( "quickbar" );
87 if ( "" == $q ) { $q = 0; }
88 return $q;
91 function initPage( &$out )
93 global $wgStyleSheetPath;
94 $fname = "Skin::initPage";
95 wfProfileIn( $fname );
97 $out->addLink( "shortcut icon", "", "/favicon.ico" );
99 wfProfileOut( $fname );
102 function outputPage( &$out ) {
103 global $wgDebugComments;
105 wfProfileIn( "Skin::outputPage" );
106 $this->initPage( $out );
107 $out->out( $out->headElement() );
109 $out->out( "\n<body" );
110 $ops = $this->getBodyOptions();
111 foreach ( $ops as $name => $val ) {
112 $out->out( " $name='$val'" );
114 $out->out( ">\n" );
115 if ( $wgDebugComments ) {
116 $out->out( "<!-- Wiki debugging output:\n" .
117 $out->mDebugtext . "-->\n" );
119 $out->out( $this->beforeContent() );
121 $out->out( $out->mBodytext );
123 $out->out( $this->afterContent() );
125 wfProfileClose();
126 $out->out( $out->reportTime() );
128 $out->out( "\n</body></html>" );
131 function getHeadScripts() {
132 global $wgStyleSheetPath;
133 $r = "<script type=\"text/javascript\" src=\"{$wgStyleSheetPath}/wikibits.js\"></script>\n";
134 return $r;
137 function getUserStyles()
139 global $wgOut, $wgStyleSheetPath;
140 $sheet = $this->getStylesheet();
141 $s = "<style type='text/css'><!--\n";
142 $s .= "/*/*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
143 $s .= "@import url(\"$wgStyleSheetPath/$sheet\");\n";
144 $s .= $this->doGetUserStyles();
145 $s .= "/* */\n";
146 $s .= "//--></style>\n";
147 return $s;
150 function doGetUserStyles()
152 global $wgUser;
154 $s = "";
155 if ( 1 == $wgUser->getOption( "underline" ) ) {
156 # Don't override browser settings
157 } else {
158 # CHECK MERGE @@@
159 # Force no underline
160 $s .= "a.stub, a.new, a.internal, a.external { " .
161 "text-decoration: none; }\n";
163 if ( 1 == $wgUser->getOption( "highlightbroken" ) ) {
164 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
166 if ( 1 == $wgUser->getOption( "justify" ) ) {
167 $s .= "#article { text-align: justify; }\n";
169 return $s;
172 function getBodyOptions()
174 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $oldid, $redirect, $diff,$action;
176 if ( 0 != $wgTitle->getNamespace() ) {
177 $a = array( "bgcolor" => "#ffffec" );
179 else $a = array( "bgcolor" => "#FFFFFF" );
180 if($wgOut->isArticle() && $wgUser->getOption("editondblclick")
182 (!$wgTitle->isProtected() || $wgUser->isSysop())
185 $t = wfMsg( "editthispage" );
186 $oid = $red = "";
187 if ( $redirect ) { $red = "&redirect={$redirect}"; }
188 if ( $oldid && ! isset( $diff ) ) {
189 $oid = "&oldid={$oldid}";
191 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
192 $s = "document.location = \"" .$s ."\";";
193 $a += array ("ondblclick" => $s);
196 $a['onload'] = $wgOut->getOnloadHandler();
197 return $a;
200 function getExternalLinkAttributes( $link, $text )
202 global $wgUser, $wgOut, $wgLang;
204 $link = urldecode( $link );
205 $link = $wgLang->checkTitleEncoding( $link );
206 $link = str_replace( "_", " ", $link );
207 $link = wfEscapeHTML( $link );
209 $r = " class='external'";
211 if ( 1 == $wgUser->getOption( "hover" ) ) {
212 $r .= " title=\"{$link}\"";
214 return $r;
217 function getInternalLinkAttributes( $link, $text, $broken = false )
219 global $wgUser, $wgOut;
221 $link = urldecode( $link );
222 $link = str_replace( "_", " ", $link );
223 $link = wfEscapeHTML( $link );
225 if ( $broken == "stub" ) {
226 $r = " class='stub'";
227 } else if ( $broken == "yes" ) {
228 $r = " class='new'";
229 } else {
230 $r = "";
233 if ( 1 == $wgUser->getOption( "hover" ) ) {
234 $r .= " title=\"{$link}\"";
236 return $r;
239 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
241 global $wgUser, $wgOut;
243 if ( $broken == "stub" ) {
244 $r = " class='stub'";
245 } else if ( $broken == "yes" ) {
246 $r = " class='new'";
247 } else {
248 $r = "";
251 if ( 1 == $wgUser->getOption( "hover" ) ) {
252 $r .= ' title ="' . $nt->getEscapedText() . '"';
254 return $r;
257 function getLogo()
259 global $wgLogo;
260 return $wgLogo;
263 # This will be called immediately after the <body> tag. Split into
264 # two functions to make it easier to subclass.
266 function beforeContent()
268 global $wgUser, $wgOut, $wgSiteNotice;
270 if( $wgSiteNotice ) {
271 $note = "\n<div id='notice' style='font-weight: bold; color: red; text-align: center'>$wgSiteNotice</div>\n";
272 } else {
273 $note = "";
275 return $this->doBeforeContent() . $note;
278 function doBeforeContent()
280 global $wgUser, $wgOut, $wgTitle, $wgLang;
281 $fname = "Skin::doBeforeContent";
282 wfProfileIn( $fname );
284 $s = "";
285 $qb = $this->qbSetting();
287 if( $langlinks = $this->otherLanguages() ) {
288 $rows = 2;
289 $borderhack = "";
290 } else {
291 $rows = 1;
292 $langlinks = false;
293 $borderhack = "class='top'";
296 $s .= "\n<div id='content'>\n<div id='topbar'>" .
297 "<table border=0 cellspacing=0><tr>";
299 $shove = ($qb != 0);
300 $left = ($qb == 1 || $qb == 3);
301 if($wgLang->isRTL()) $left = !$left;
303 if ( !$shove ) {
304 $s .= "<td class='top' align=left valign=top rowspan='{$rows}'>" .
305 $this->logoText() . "</td>";
306 } elseif( $left ) {
307 $s .= $this->getQuickbarCompensator( $rows );
309 $l = $wgLang->isRTL() ? "right" : "left";
310 $s .= "<td {$borderhack} align='$l' valign='top'>";
312 $s .= $this->topLinks() ;
313 $s .= "<p class='subtitle'>" . $this->pageTitleLinks();
315 $r = $wgLang->isRTL() ? "left" : "right";
316 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap>";
317 $s .= $this->nameAndLogin();
318 $s .= "\n<br>" . $this->searchForm() . "</td>";
320 if ( $langlinks ) {
321 $s .= "</tr>\n<tr><td class='top' colspan=\"2\">$langlinks</td>";
324 if ( $shove && !$left ) { # Right
325 $s .= $this->getQuickbarCompensator( $rows );
327 $s .= "</tr></table>\n</div>\n";
328 $s .= "\n<div id='article'>";
330 $s .= $this->pageTitle();
331 $s .= $this->pageSubtitle() ;
332 $s .= getCategories(); // For some odd reason, zhis can't be a function of the object
333 $s .= "\n<p>";
334 wfProfileOut( $fname );
335 return $s;
338 function getQuickbarCompensator( $rows = 1 )
340 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
343 # This gets called immediately before the </body> tag.
345 function afterContent()
347 global $wgUser, $wgOut, $wgServer;
348 global $wgTitle, $wgLang;
350 $printfooter = "<div class=\"printfooter\">" . $this->printFooter() . "</div>\n";
351 return $printfooter . $this->doAfterContent();
354 function printFooter() {
355 global $wgTitle;
356 $url = htmlspecialchars( $wgTitle->getFullURL() );
357 return "<p>" . wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" ) .
358 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
361 function doAfterContent()
363 global $wgUser, $wgOut, $wgLang;
364 $fname = "Skin::doAfterContent";
365 wfProfileIn( $fname );
366 wfProfileIn( "$fname-1" );
368 $s = "\n</div><br clear=all>\n";
369 $s .= "\n<div id='footer'>";
370 $s .= "<table border=0 cellspacing=0><tr>";
372 wfProfileOut( "$fname-1" );
373 wfProfileIn( "$fname-2" );
375 $qb = $this->qbSetting();
376 $shove = ($qb != 0);
377 $left = ($qb == 1 || $qb == 3);
378 if($wgLang->isRTL()) $left = !$left;
380 if ( $shove && $left ) { # Left
381 $s .= $this->getQuickbarCompensator();
383 wfProfileOut( "$fname-2" );
384 wfProfileIn( "$fname-3" );
385 $l = $wgLang->isRTL() ? "right" : "left";
386 $s .= "<td class='bottom' align='$l' valign='top'>";
388 $s .= $this->bottomLinks();
389 $s .= "\n<br>" . $this->mainPageLink()
390 . " | " . $this->aboutLink()
391 . " | " . $this->specialLink( "recentchanges" )
392 . " | " . $this->searchForm()
393 . "<br><span id='pagestats'>" . $this->pageStats() . "</span>";
395 $s .= "</td>";
396 if ( $shove && !$left ) { # Right
397 $s .= $this->getQuickbarCompensator();
399 $s .= "</tr></table>\n</div>\n</div>\n";
401 wfProfileOut( "$fname-3" );
402 wfProfileIn( "$fname-4" );
403 if ( 0 != $qb ) { $s .= $this->quickBar(); }
404 wfProfileOut( "$fname-4" );
405 wfProfileOut( $fname );
406 return $s;
409 function pageTitleLinks()
411 global $wgOut, $wgTitle, $oldid, $action, $diff, $wgUser, $wgLang, $wgUseApproval;
413 $s = $this->printableLink();
414 if ( wfMsg ( "disclaimers" ) != "-" ) $s .= " | " . $this->makeKnownLink( wfMsg( "disclaimerpage" ), wfMsg( "disclaimers" ) ) ;
416 if ( $wgOut->isArticleRelated() ) {
417 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
418 $name = $wgTitle->getDBkey();
419 $link = wfEscapeHTML( wfImageUrl( $name ) );
420 $style = $this->getInternalLinkAttributes( $link, $name );
421 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
423 # This will show the "Approve" link if $wgUseApproval=true;
424 if ( isset ( $wgUseApproval ) && $wgUseApproval )
426 $t = $wgTitle->getDBkey();
427 $name = "Approve this article" ;
428 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
429 #wfEscapeHTML( wfImageUrl( $name ) );
430 $style = $this->getExternalLinkAttributes( $link, $name );
431 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
434 if ( "history" == $action || isset( $diff ) || isset( $oldid ) ) {
435 $s .= " | " . $this->makeKnownLink( $wgTitle->getPrefixedText(),
436 wfMsg( "currentrev" ) );
439 if ( $wgUser->getNewtalk() ) {
440 # do not show "You have new messages" text when we are viewing our
441 # own talk page
443 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
444 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
445 $n =$wgUser->getName();
446 $tl = $this->makeKnownLink( $wgLang->getNsText(
447 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
448 wfMsg("newmessageslink") );
449 $s.=" | <strong>". wfMsg( "newmessages", $tl ) . "</strong>";
452 if( $wgUser->isSysop() &&
453 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
454 ($n = $wgTitle->isDeleted() ) ) {
455 $s .= " | " . wfMsg( "thisisdeleted",
456 $this->makeKnownLink(
457 $wgLang->SpecialPage( "Undelete/" . $wgTitle->getPrefixedDBkey() ),
458 wfMsg( "restorelink", $n ) ) );
460 return $s;
463 function printableLink()
465 global $wgOut, $wgFeedClasses, $wgRequest;
467 $baseurl = $_SERVER['REQUEST_URI'];
468 if( strpos( "?", $baseurl ) == false ) {
469 $baseurl .= "?";
470 } else {
471 $baseurl .= "&";
473 $baseurl = htmlspecialchars( $baseurl );
474 $printurl = $wgRequest->escapeAppendQuery( "printable=yes" );
476 $s = "<a href=\"$printurl\">" . wfMsg( "printableversion" ) . "</a>";
477 if( $wgOut->isSyndicated() ) {
478 foreach( $wgFeedClasses as $format => $class ) {
479 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
480 $s .= " | <a href=\"$feedurl\">{$format}</a>";
483 return $s;
486 function pageTitle()
488 global $wgOut, $wgTitle, $wgUser;
490 $s = "<h1 class='pagetitle'>" . $wgOut->getPageTitle() . "</h1>";
491 if($wgUser->getOption("editsectiononrightclick") && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
492 return $s;
495 function pageSubtitle()
497 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
499 $sub = $wgOut->getSubtitle();
500 if ( "" == $sub ) {
501 global $wgExtraSubtitle;
502 $sub = wfMsg( "fromwikipedia" ) . $wgExtraSubtitle;
504 if($wgOut->isArticle() && $wgNamespacesWithSubpages[$wgTitle->getNamespace()]) {
505 $ptext=$wgTitle->getPrefixedText();
506 if(preg_match("/\//",$ptext)) {
507 $sub.="</p><p class='subpages'>";
508 $links=explode("/",$ptext);
509 $c=0;
510 $growinglink="";
511 foreach($links as $link) {
512 $c++;
513 if ($c<count($links)) {
514 $growinglink .= $link;
515 $getlink = $this->makeLink( $growinglink, $link );
516 if(preg_match("/class='new'/i",$getlink)) { break; } # this is a hack, but it saves time
517 if ($c>1) {
518 $sub .= " | ";
519 } else {
520 $sub .="&lt; ";
522 $sub .= $getlink;
523 $growinglink.="/";
529 $s = "<p class='subtitle'>{$sub}\n";
530 return $s;
533 function nameAndLogin()
535 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
537 $li = $wgLang->specialPage( "Userlogin" );
538 $lo = $wgLang->specialPage( "Userlogout" );
540 $s = "";
541 if ( 0 == $wgUser->getID() ) {
542 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get("session.name")] ) ) {
543 $n = $wgIP;
545 $tl = $this->makeKnownLink( $wgLang->getNsText(
546 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
547 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
549 $s .= $n . " (".$tl.")";
550 } else {
551 $s .= wfMsg("notloggedin");
554 $rt = $wgTitle->getPrefixedURL();
555 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
556 $q = "";
557 } else { $q = "returnto={$rt}"; }
559 $s .= "\n<br>" . $this->makeKnownLink( $li,
560 wfMsg( "login" ), $q );
561 } else {
562 $n = $wgUser->getName();
563 $rt = $wgTitle->getPrefixedURL();
564 $tl = $this->makeKnownLink( $wgLang->getNsText(
565 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
566 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
568 $tl = " ({$tl})";
570 $s .= $this->makeKnownLink( $wgLang->getNsText(
571 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br>" .
572 $this->makeKnownLink( $lo, wfMsg( "logout" ),
573 "returnto={$rt}" ) . " | " .
574 $this->specialLink( "preferences" );
576 $s .= " | " . $this->makeKnownLink( wfMsg( "helppage" ),
577 wfMsg( "help" ) );
579 return $s;
582 function searchForm()
584 global $search;
586 $s = "<form name='search' class='inline' method=post action=\""
587 . wfLocalUrl( "" ) . "\">"
588 . "<input type=text name=\"search\" size=19 value=\""
589 . htmlspecialchars(substr($search,0,256)) . "\">\n"
590 . "<input type=submit name=\"go\" value=\"" . wfMsg ("go") . "\">&nbsp;"
591 . "<input type=submit name=\"fulltext\" value=\"" . wfMsg ("search") . "\"></form>";
593 return $s;
596 function topLinks()
598 global $wgOut;
599 $sep = " |\n";
601 $s = $this->mainPageLink() . $sep
602 . $this->specialLink( "recentchanges" );
604 if ( $wgOut->isArticleRelated() ) {
605 $s .= $sep . $this->editThisPage()
606 . $sep . $this->historyLink();
608 # Many people don't like this dropdown box
609 #$s .= $sep . $this->specialPagesList();
611 return $s;
614 function bottomLinks()
616 global $wgOut, $wgUser, $wgTitle;
617 $sep = " |\n";
619 $s = "";
620 if ( $wgOut->isArticleRelated() ) {
621 $s .= "<strong>" . $this->editThisPage() . "</strong>";
622 if ( 0 != $wgUser->getID() ) {
623 $s .= $sep . $this->watchThisPage();
625 $s .= $sep . $this->talkLink()
626 . $sep . $this->historyLink()
627 . $sep . $this->whatLinksHere()
628 . $sep . $this->watchPageLinksLink();
630 if ( $wgTitle->getNamespace() == Namespace::getUser()
631 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
634 $id=User::idFromName($wgTitle->getText());
635 $ip=User::isIP($wgTitle->getText());
637 if($id || $ip) { # both anons and non-anons have contri list
638 $s .= $sep . $this->userContribsLink();
640 if ( 0 != $wgUser->getID() ) { # show only to signed in users
641 if($id) { # can only email non-anons
642 $s .= $sep . $this->emailUserLink();
646 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
647 $s .= "\n<br>" . $this->deleteThisPage() .
648 $sep . $this->protectThisPage() .
649 $sep . $this->moveThisPage();
651 $s .= "<br>\n" . $this->otherLanguages();
653 return $s;
656 function pageStats()
658 global $wgOut, $wgLang, $wgArticle;
659 global $oldid, $diff, $wgDisableCounters;
661 if ( ! $wgOut->isArticle() ) { return ""; }
662 if ( isset( $oldid ) || isset( $diff ) ) { return ""; }
663 if ( 0 == $wgArticle->getID() ) { return ""; }
665 if ( $wgDisableCounters ) {
666 $s = "";
667 } else {
668 $count = $wgLang->formatNum( $wgArticle->getCount() );
669 $s = wfMsg( "viewcount", $count );
671 $s .= $this->lastModified();
672 $s .= " " . wfMsg( "gnunote" );
673 return $s;
676 function lastModified()
678 global $wgLang, $wgArticle;
680 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
681 $s = " " . wfMsg( "lastmodified", $d );
682 return $s;
685 function logoText( $align = "" )
687 if ( "" != $align ) { $a = " align='{$align}'"; }
688 else { $a = ""; }
690 $mp = wfMsg( "mainpage" );
691 $titleObj = Title::newFromText( $mp );
692 $s = "<a href=\"" . $titleObj->escapeLocalURL()
693 . "\"><img{$a} border=0 src=\""
694 . $this->getLogo() . "\" alt=\"" . "[{$mp}]\" /></a>";
695 return $s;
698 function quickBar()
700 global $wgOut, $wgTitle, $wgUser, $action, $wgLang;
701 global $wpPreview, $wgDisableUploads, $wgRemoteUploads;
703 $fname = "Skin::quickBar";
704 wfProfileIn( $fname );
706 $tns=$wgTitle->getNamespace();
708 $s = "\n<div id='quickbar'>";
709 $s .= "\n" . $this->logoText() . "\n<hr class='sep'>";
711 $sep = "\n<br>";
712 $s .= $this->mainPageLink()
713 . $sep . $this->specialLink( "recentchanges" )
714 . $sep . $this->specialLink( "randompage" );
715 if ($wgUser->getID()) {
716 $s.= $sep . $this->specialLink( "watchlist" ) ;
717 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
718 wfMsg( "mycontris" ), "target=" . wfUrlencode($wgUser->getName() ) );
721 // only show watchlist link if logged in
722 if ( wfMsg ( "currentevents" ) != "-" ) $s .= $sep . $this->makeKnownLink( wfMsg( "currentevents" ), "" ) ;
723 $s .= "\n<br><hr class='sep'>";
724 $articleExists = $wgTitle->getArticleId();
725 if ( $wgOut->isArticle() || $action =="edit" || $action =="history" || $wpPreview) {
726 if($wgOut->isArticle()) {
727 $s .= "<strong>" . $this->editThisPage() . "</strong>";
728 } else { # backlink to the article in edit or history mode
729 if($articleExists){ # no backlink if no article
730 switch($tns) {
731 case 0:
732 $text = wfMsg("articlepage");
733 break;
734 case 1:
735 $text = wfMsg("viewtalkpage");
736 break;
737 case 2:
738 $text = wfMsg("userpage");
739 break;
740 case 3:
741 $text = wfMsg("viewtalkpage");
742 break;
743 case 4:
744 $text = wfMsg("wikipediapage");
745 break;
746 case 5:
747 $text = wfMsg("viewtalkpage");
748 break;
749 case 6:
750 $text = wfMsg("imagepage");
751 break;
752 case 7:
753 $text = wfMsg("viewtalkpage");
754 break;
755 default:
756 $text= wfMsg("articlepage");
759 $link = $wgTitle->getText();
760 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
761 $link = $nstext . ":" . $link ;
764 $s .= $this->makeLink( $link, $text );
765 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
766 # we just throw in a "New page" text to tell the user that he's in edit mode,
767 # and to avoid messing with the separator that is prepended to the next item
768 $s .= "<strong>" . wfMsg("newpage") . "</strong>";
774 if( $tns%2 && $action!="edit" && !$wpPreview) {
775 $s.="<br>".$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("postcomment"),"action=edit&section=new");
779 watching could cause problems in edit mode:
780 if user edits article, then loads "watch this article" in background and then saves
781 article with "Watch this article" checkbox disabled, the article is transparently
782 unwatched. Therefore we do not show the "Watch this page" link in edit mode
784 if ( 0 != $wgUser->getID() && $articleExists) {
785 if($action!="edit" && $action != "submit" )
787 $s .= $sep . $this->watchThisPage();
789 if ( $wgTitle->userCanEdit() )
790 $s .= $sep . $this->moveThisPage();
792 if ( $wgUser->isSysop() and $articleExists ) {
793 $s .= $sep . $this->deleteThisPage() .
794 $sep . $this->protectThisPage();
796 $s .= $sep . $this->talkLink();
797 if ($articleExists && $action !="history") {
798 $s .= $sep . $this->historyLink();
800 $s.=$sep . $this->whatLinksHere();
802 if($wgOut->isArticleRelated()) {
803 $s .= $sep . $this->watchPageLinksLink();
806 if ( Namespace::getUser() == $wgTitle->getNamespace()
807 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
810 $id=User::idFromName($wgTitle->getText());
811 $ip=User::isIP($wgTitle->getText());
813 if($id||$ip) {
814 $s .= $sep . $this->userContribsLink();
816 if ( 0 != $wgUser->getID() ) {
817 if($id) { # can only email real users
818 $s .= $sep . $this->emailUserLink();
822 $s .= "\n<br><hr class='sep'>";
825 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
826 $s .= $this->specialLink( "upload" ) . $sep;
828 $s .= $this->specialLink( "specialpages" )
829 . $sep . $this->bugReportsLink();
831 global $wgSiteSupportPage;
832 if( $wgSiteSupportPage ) {
833 $s .= "\n<br><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
834 "\" class=\"internal\">" . wfMsg( "sitesupport" ) . "</a>";
837 $s .= "\n<br></div>\n";
838 wfProfileOut( $fname );
839 return $s;
842 function specialPagesList()
844 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
845 $a = array();
847 $validSP = $wgLang->getValidSpecialPages();
849 foreach ( $validSP as $name => $desc ) {
850 if ( "" == $desc ) { continue; }
851 $a[$name] = $desc;
853 if ( $wgUser->isSysop() )
855 $sysopSP = $wgLang->getSysopSpecialPages();
857 foreach ( $sysopSP as $name => $desc ) {
858 if ( "" == $desc ) { continue; }
859 $a[$name] = $desc ;
862 if ( $wgUser->isDeveloper() )
864 $devSP = $wgLang->getDeveloperSpecialPages();
866 foreach ( $devSP as $name => $desc ) {
867 if ( "" == $desc ) { continue; }
868 $a[$name] = $desc ;
871 $go = wfMsg( "go" );
872 $sp = wfMsg( "specialpages" );
873 $spp = $wgLang->specialPage( "Specialpages" );
875 $s = "<form id=\"specialpages\" method=\"get\" class=\"inline\" " .
876 "action=\"{$wgServer}{$wgRedirectScript}\">\n";
877 $s .= "<select name=\"wpDropdown\">\n";
878 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
880 foreach ( $a as $name => $desc ) {
881 $p = $wgLang->specialPage( $name );
882 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
884 $s .= "</select>\n";
885 $s .= "<input type=submit value=\"{$go}\" name=redirect>\n";
886 $s .= "</form>\n";
887 return $s;
890 function mainPageLink()
892 $mp = wfMsg( "mainpage" );
893 $s = $this->makeKnownLink( $mp, $mp );
894 return $s;
897 function copyrightLink()
899 $s = $this->makeKnownLink( wfMsg( "copyrightpage" ),
900 wfMsg( "copyrightpagename" ) );
901 return $s;
904 function aboutLink()
906 $s = $this->makeKnownLink( wfMsg( "aboutpage" ),
907 wfMsg( "aboutwikipedia" ) );
908 return $s;
912 function disclaimerLink()
914 $s = $this->makeKnownLink( wfMsg( "disclaimerpage" ),
915 wfMsg( "disclaimers" ) );
916 return $s;
919 function editThisPage()
921 global $wgOut, $wgTitle, $oldid, $redirect, $diff;
923 if ( ! $wgOut->isArticleRelated() ) {
924 $s = wfMsg( "protectedpage" );
925 } else {
926 $n = $wgTitle->getPrefixedText();
927 if ( $wgTitle->userCanEdit() ) {
928 $t = wfMsg( "editthispage" );
929 } else {
930 #$t = wfMsg( "protectedpage" );
931 $t = wfMsg( "viewsource" );
933 $oid = $red = "";
935 if ( $redirect ) { $red = "&redirect={$redirect}"; }
936 if ( $oldid && ! isset( $diff ) ) {
937 $oid = "&oldid={$oldid}";
939 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
941 return $s;
944 function deleteThisPage()
946 global $wgUser, $wgOut, $wgTitle, $diff;
948 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
949 $n = $wgTitle->getPrefixedText();
950 $t = wfMsg( "deletethispage" );
952 $s = $this->makeKnownLink( $n, $t, "action=delete" );
953 } else {
954 $s = "";
956 return $s;
959 function protectThisPage()
961 global $wgUser, $wgOut, $wgTitle, $diff;
963 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
964 $n = $wgTitle->getPrefixedText();
966 if ( $wgTitle->isProtected() ) {
967 $t = wfMsg( "unprotectthispage" );
968 $q = "action=unprotect";
969 } else {
970 $t = wfMsg( "protectthispage" );
971 $q = "action=protect";
973 $s = $this->makeKnownLink( $n, $t, $q );
974 } else {
975 $s = "";
977 return $s;
980 function watchThisPage()
982 global $wgUser, $wgOut, $wgTitle, $diff;
984 if ( $wgOut->isArticleRelated() ) {
985 $n = $wgTitle->getPrefixedText();
987 if ( $wgTitle->userIsWatching() ) {
988 $t = wfMsg( "unwatchthispage" );
989 $q = "action=unwatch";
990 } else {
991 $t = wfMsg( "watchthispage" );
992 $q = "action=watch";
994 $s = $this->makeKnownLink( $n, $t, $q );
995 } else {
996 $s = wfMsg( "notanarticle" );
998 return $s;
1001 function moveThisPage()
1003 global $wgTitle, $wgLang;
1005 if ( $wgTitle->userCanEdit() ) {
1006 $s = $this->makeKnownLink( $wgLang->specialPage( "Movepage" ),
1007 wfMsg( "movethispage" ), "target=" . $wgTitle->getPrefixedURL() );
1008 } // no message if page is protected - would be redundant
1009 return $s;
1012 function historyLink()
1014 global $wgTitle;
1016 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1017 wfMsg( "history" ), "action=history" );
1018 return $s;
1021 function whatLinksHere()
1023 global $wgTitle, $wgLang;
1025 $s = $this->makeKnownLink( $wgLang->specialPage( "Whatlinkshere" ),
1026 wfMsg( "whatlinkshere" ), "target=" . $wgTitle->getPrefixedURL() );
1027 return $s;
1030 function userContribsLink()
1032 global $wgTitle, $wgLang;
1034 $s = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1035 wfMsg( "contributions" ), "target=" . $wgTitle->getPartialURL() );
1036 return $s;
1039 function emailUserLink()
1041 global $wgTitle, $wgLang;
1043 $s = $this->makeKnownLink( $wgLang->specialPage( "Emailuser" ),
1044 wfMsg( "emailuser" ), "target=" . $wgTitle->getPartialURL() );
1045 return $s;
1048 function watchPageLinksLink()
1050 global $wgOut, $wgTitle, $wgLang;
1052 if ( ! $wgOut->isArticleRelated() ) {
1053 $s = "(" . wfMsg( "notanarticle" ) . ")";
1054 } else {
1055 $s = $this->makeKnownLink( $wgLang->specialPage(
1056 "Recentchangeslinked" ), wfMsg( "recentchangeslinked" ),
1057 "target=" . $wgTitle->getPrefixedURL() );
1059 return $s;
1062 function otherLanguages()
1064 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1066 $a = $wgOut->getLanguageLinks();
1067 # TEST THIS @@@
1068 if ( 0 == count( $a ) ) {
1069 if ( !$wgUseNewInterlanguage ) return "";
1070 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1071 if ( $ns != 0 AND $ns != 1 ) return "" ;
1072 $pn = "Intl" ;
1073 $x = "mode=addlink&xt=".$wgTitle->getDBkey() ;
1074 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1075 wfMsg( "intl" ) , $x );
1078 if ( !$wgUseNewInterlanguage ) {
1079 $s = wfMsg( "otherlanguages" ) . ": ";
1080 } else {
1081 global $wgLanguageCode ;
1082 $x = "mode=zoom&xt=".$wgTitle->getDBkey() ;
1083 $x .= "&xl=".$wgLanguageCode ;
1084 $s = $this->makeKnownLink( $wgLang->specialPage( "Intl" ),
1085 wfMsg( "otherlanguages" ) , $x ) . ": " ;
1088 $s = wfMsg( "otherlanguages" ) . ": ";
1089 $first = true;
1090 if($wgLang->isRTL()) $s .= "<span dir='LTR'>";
1091 foreach( $a as $l ) {
1092 if ( ! $first ) { $s .= " | "; }
1093 $first = false;
1095 $nt = Title::newFromText( $l );
1096 $url = $nt->getFullURL();
1097 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1099 if ( "" == $text ) { $text = $l; }
1100 $style = $this->getExternalLinkAttributes( $l, $text );
1101 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1103 if($wgLang->isRTL()) $s .= "</span>";
1104 return $s;
1107 function bugReportsLink()
1109 $s = $this->makeKnownLink( wfMsg( "bugreportspage" ),
1110 wfMsg( "bugreports" ) );
1111 return $s;
1114 function dateLink()
1116 global $wgLinkCache;
1117 $t1 = Title::newFromText( gmdate( "F j" ) );
1118 $t2 = Title::newFromText( gmdate( "Y" ) );
1120 $wgLinkCache->suspend();
1121 $id = $t1->getArticleID();
1122 $wgLinkCache->resume();
1124 if ( 0 == $id ) {
1125 $s = $this->makeBrokenLink( $t1->getText() );
1126 } else {
1127 $s = $this->makeKnownLink( $t1->getText() );
1129 $s .= ", ";
1131 $wgLinkCache->suspend();
1132 $id = $t2->getArticleID();
1133 $wgLinkCache->resume();
1135 if ( 0 == $id ) {
1136 $s .= $this->makeBrokenLink( $t2->getText() );
1137 } else {
1138 $s .= $this->makeKnownLink( $t2->getText() );
1140 return $s;
1143 function talkLink()
1145 global $wgLang, $wgTitle, $wgLinkCache;
1147 $tns = $wgTitle->getNamespace();
1148 if ( -1 == $tns ) { return ""; }
1150 $pn = $wgTitle->getText();
1151 $tp = wfMsg( "talkpage" );
1152 if ( Namespace::isTalk( $tns ) ) {
1153 $lns = Namespace::getSubject( $tns );
1154 switch($tns) {
1155 case 1:
1156 $text = wfMsg("articlepage");
1157 break;
1158 case 3:
1159 $text = wfMsg("userpage");
1160 break;
1161 case 5:
1162 $text = wfMsg("wikipediapage");
1163 break;
1164 case 7:
1165 $text = wfMsg("imagepage");
1166 break;
1167 default:
1168 $text= wfMsg("articlepage");
1170 } else {
1172 $lns = Namespace::getTalk( $tns );
1173 $text=$tp;
1175 $n = $wgLang->getNsText( $lns );
1176 if ( "" == $n ) { $link = $pn; }
1177 else { $link = "{$n}:{$pn}"; }
1179 $wgLinkCache->suspend();
1180 $s = $this->makeLink( $link, $text );
1181 $wgLinkCache->resume();
1183 return $s;
1186 function commentLink()
1188 global $wgLang, $wgTitle, $wgLinkCache;
1190 $tns = $wgTitle->getNamespace();
1191 if ( -1 == $tns ) { return ""; }
1193 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1195 # assert Namespace::isTalk( $lns )
1197 $n = $wgLang->getNsText( $lns );
1198 $pn = $wgTitle->getText();
1200 $link = "{$n}:{$pn}";
1202 $wgLinkCache->suspend();
1203 $s = $this->makeKnownLink($link, wfMsg("postcomment"), "action=edit&section=new");
1204 $wgLinkCache->resume();
1206 return $s;
1209 # After all the page content is transformed into HTML, it makes
1210 # a final pass through here for things like table backgrounds.
1212 function transformContent( $text )
1214 return $text;
1217 # Note: This function MUST call getArticleID() on the link,
1218 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1220 function makeLink( $title, $text = "", $query = "", $trail = "" ) {
1221 wfProfileIn( "Skin::makeLink" );
1222 $nt = Title::newFromText( $title );
1223 if ($nt) {
1224 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1225 } else {
1226 wfDebug( "Invalid title passed to Skin::makeLink(): \"$title\"\n" );
1227 $result = $text == "" ? $title : $text;
1230 wfProfileOut( "Skin::makeLink" );
1231 return $result;
1234 function makeKnownLink( $title, $text = "", $query = "", $trail = "" ) {
1235 $nt = Title::newFromText( $title );
1236 if ($nt) {
1237 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1238 } else {
1239 wfDebug( "Invalid title passed to Skin::makeKnownLink(): \"$title\"\n" );
1240 return $text == "" ? $title : $text;
1244 function makeBrokenLink( $title, $text = "", $query = "", $trail = "" ) {
1245 $nt = Title::newFromText( $title );
1246 if ($nt) {
1247 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1248 } else {
1249 wfDebug( "Invalid title passed to Skin::makeBrokenLink(): \"$title\"\n" );
1250 return $text == "" ? $title : $text;
1254 function makeStubLink( $title, $text = "", $query = "", $trail = "" ) {
1255 $nt = Title::newFromText( $title );
1256 if ($nt) {
1257 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1258 } else {
1259 wfDebug( "Invalid title passed to Skin::makeStubLink(): \"$title\"\n" );
1260 return $text == "" ? $title : $text;
1264 # Pass a title object, not a title string
1265 function makeLinkObj( &$nt, $text= "", $query = "", $trail = "", $prefix = "" )
1267 global $wgOut, $wgUser;
1268 if ( $nt->isExternal() ) {
1269 $u = $nt->getFullURL();
1270 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1271 $style = $this->getExternalLinkAttributes( $link, $text );
1273 $inside = "";
1274 if ( "" != $trail ) {
1275 if ( preg_match( "/^([a-z]+)(.*)$$/sD", $trail, $m ) ) {
1276 $inside = $m[1];
1277 $trail = $m[2];
1280 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1281 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1282 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1283 } elseif ( ( -1 == $nt->getNamespace() ) ||
1284 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1285 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1286 } else {
1287 $aid = $nt->getArticleID() ;
1288 if ( 0 == $aid ) {
1289 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1290 } else {
1291 $threshold = $wgUser->getOption("stubthreshold") ;
1292 if ( $threshold > 0 ) {
1293 $res = wfQuery ( "SELECT LENGTH(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ ) ;
1295 if ( wfNumRows( $res ) > 0 ) {
1296 $s = wfFetchObject( $res );
1297 $size = $s->x;
1298 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1299 $size = $threshold*2 ; # Really big
1301 wfFreeResult( $res );
1302 } else {
1303 $size = $threshold*2 ; # Really big
1305 } else {
1306 $size = 1 ;
1308 if ( $size < $threshold ) {
1309 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1310 } else {
1311 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1315 return $retVal;
1318 # Pass a title object, not a title string
1319 function makeKnownLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" )
1321 global $wgOut, $wgTitle;
1323 $fname = "Skin::makeKnownLinkObj";
1324 wfProfileIn( $fname );
1326 $link = $nt->getPrefixedURL();
1328 if ( "" == $link ) {
1329 $u = "";
1330 if ( "" == $text ) { $text = $nt->getFragment(); }
1331 } else {
1332 $u = $nt->escapeLocalURL( $query );
1334 if ( "" != $nt->getFragment() ) {
1335 $u .= "#" . wfEscapeHTML( $nt->getFragment() );
1337 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1338 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1340 $inside = "";
1341 if ( "" != $trail ) {
1342 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1343 $inside = $m[1];
1344 $trail = $m[2];
1347 $r = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1348 wfProfileOut( $fname );
1349 return $r;
1352 # Pass a title object, not a title string
1353 function makeBrokenLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" )
1355 global $wgOut, $wgUser;
1357 $fname = "Skin::makeBrokenLinkObj";
1358 wfProfileIn( $fname );
1360 if ( "" == $query ) {
1361 $q = "action=edit";
1362 } else {
1363 $q = "action=edit&{$query}";
1365 $u = $nt->escapeLocalURL( $q );
1367 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1368 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1370 $inside = "";
1371 if ( "" != $trail ) {
1372 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1373 $inside = $m[1];
1374 $trail = $m[2];
1377 if ( $wgUser->getOption( "highlightbroken" ) ) {
1378 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1379 } else {
1380 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1383 wfProfileOut( $fname );
1384 return $s;
1387 # Pass a title object, not a title string
1388 function makeStubLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" )
1390 global $wgOut, $wgUser;
1392 $link = $nt->getPrefixedURL();
1394 $u = $nt->escapeLocalURL( $query );
1396 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1397 $style = $this->getInternalLinkAttributesObj( $nt, $text, "stub" );
1399 $inside = "";
1400 if ( "" != $trail ) {
1401 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1402 $inside = $m[1];
1403 $trail = $m[2];
1406 if ( $wgUser->getOption( "highlightbroken" ) ) {
1407 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1408 } else {
1409 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1411 return $s;
1414 function fnamePart( $url )
1416 $basename = strrchr( $url, "/" );
1417 if ( false === $basename ) { $basename = $url; }
1418 else { $basename = substr( $basename, 1 ); }
1419 return wfEscapeHTML( $basename );
1422 function makeImage( $url, $alt = "" )
1424 global $wgOut;
1426 if ( "" == $alt ) { $alt = $this->fnamePart( $url ); }
1427 $s = "<img src=\"{$url}\" alt=\"{$alt}\" />";
1428 return $s;
1431 function makeImageLink( $name, $url, $alt = "" ) {
1432 $nt = Title::makeTitle( Namespace::getImage(), $name );
1433 return $this->makeImageLinkObj( $nt, $alt );
1436 function makeImageLinkObj( $nt, $alt = "" ) {
1437 global $wgLang, $wgUseImageResize;
1438 $name = $nt->getDBKey();
1439 $url = wfImageUrl( $name );
1440 $align = "";
1441 $prefix = $postfix = "";
1443 if ( $wgUseImageResize ) {
1444 # Check if the alt text is of the form "options|alt text"
1445 # Options are:
1446 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1447 # * left no resizing, just left align. label is used for alt= only
1448 # * right same, but right aligned
1449 # * none same, but not aligned
1450 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1452 $part = explode( "|", $alt);
1454 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1455 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1456 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1457 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1458 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1459 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1460 $alt = $part[count($part)-1];
1462 $thumb=false;
1464 foreach( $part as $key => $val ) {
1465 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1466 $thumb=true;
1467 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1468 # remember to set an alignment, don't render immediately
1469 $align = "right";
1470 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1471 # remember to set an alignment, don't render immediately
1472 $align = "left";
1473 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1474 # remember to set an alignment, don't render immediately
1475 $align = "center";
1476 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1477 # remember to set an alignment, don't render immediately
1478 $align = "none";
1479 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1480 # $match is the image width in pixels
1481 $width = intval($match);
1484 if ( "center" == $align )
1486 $prefix = "<center>";
1487 $postfix = "</center>";
1488 $align = "none";
1491 if ( $thumb ) {
1493 # Create a thumbnail. Alignment depends on language
1494 # writing direction, # right aligned for left-to-right-
1495 # languages ("Western languages"), left-aligned
1496 # for right-to-left-languages ("Semitic languages")
1498 # If thumbnail width has not been provided, it is set
1499 # here to 180 pixels
1500 if ( $align == "" ) {
1501 $align = $wgLang->isRTL() ? "left" : "right";
1503 if ( ! isset($width) ) {
1504 $width = 180;
1506 return $prefix.$this->makeThumbLinkObj( $nt, $alt, $align, $width ).$postfix;
1508 } elseif ( isset($width) ) {
1510 # Create a resized image, without the additional thumbnail
1511 # features
1512 $url = $this->createThumb( $name, $width );
1514 } # endif $wgUseImageResize
1516 if ( empty( $alt ) ) {
1517 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1519 $alt = htmlspecialchars( $alt );
1521 $u = $nt->escapeLocalURL();
1522 if ( $url == "" )
1524 $s = str_replace( "$1", $name, wfMsg("missingimage") );
1525 } else {
1526 $s = "\n <a href=\"{$u}\" class='image' title=\"{$alt}\">\n" .
1527 " <img border=\"0\" src=\"{$url}\" alt=\"{$alt}\" />\n </a>";
1529 if ( "" != $align ) {
1530 $s = "<div class=\"float{$align}\">{$s}\n</div>";
1532 return $prefix.$s.$postfix;
1535 function createThumb( $name, $width ) {
1536 global $wgUploadDirectory;
1537 global $wgImageMagickConvertCommand;
1538 global $wgUseImageMagick;
1539 global $wgUseSquid, $wgInternalServer;
1540 $imgPath = wfImagePath( $name );
1541 $thumbName = $width."px-".$icon.$name;
1542 $thumbPath = wfImageThumbDir( $thumbName )."/".$thumbName;
1543 $thumbUrl = wfImageThumbUrl( $thumbName );
1545 if ( ! file_exists( $imgPath ) )
1547 # If there is no image, there will be no thumbnail
1548 return "";
1551 if ( (! file_exists( $thumbPath ) )
1552 || ( filemtime($thumbPath) < filemtime($imgPath) ) ) {
1553 # Squid purging
1554 if ( $wgUseSquid ) {
1555 $urlArr = Array(
1556 $wgInternalServer.$thumbUrl
1558 wfPurgeSquidServers($urlArr);
1561 if ( $wgUseImageMagick ) {
1562 # use ImageMagick
1563 $cmd = $wgImageMagickConvertCommand .
1564 " -quality 85 -geometry {$width} ".
1565 escapeshellarg($imgPath) . " " .
1566 escapeshellarg($thumbPath);
1567 $conv = shell_exec( $cmd );
1568 } else {
1569 # Use PHP's builtin GD library functions.
1571 # First find out what kind of file this is, and select the correct
1572 # input routine for this.
1573 list($src_width, $src_height, $src_type, $src_attr) = getimagesize( $imgPath );
1574 switch( $src_type ) {
1575 case 1: # GIF
1576 $src_image = imagecreatefromgif( $imgPath );
1577 break;
1578 case 2: # JPG
1579 $src_image = imagecreatefromjpeg( $imgPath );
1580 break;
1581 case 3: # PNG
1582 $src_image = imagecreatefrompng( $imgPath );
1583 break;
1584 case 15: # WBMP for WML
1585 $src_image = imagecreatefromwbmp( $imgPath );
1586 break;
1587 case 16: # XBM
1588 $src_image = imagecreatefromxbm( $imgPath );
1589 break;
1590 default:
1591 return "Image type not supported";
1592 break;
1594 $height = floor( $src_height * ( $width/$src_width ) );
1595 $dst_image = imagecreatetruecolor( $width, $height );
1596 imagecopyresampled( $dst_image, $src_image,
1597 0,0,0,0,
1598 $width, $height, $src_width, $src_height );
1599 switch( $src_type ) {
1600 case 1: # GIF
1601 case 3: # PNG
1602 case 15: # WBMP
1603 case 16: # XBM
1604 #$thumbUrl .= ".png";
1605 #$thumbPath .= ".png";
1606 imagepng( $dst_image, $thumbPath );
1607 break;
1608 case 2: # JPEG
1609 #$thumbUrl .= ".jpg";
1610 #$thumbPath .= ".jpg";
1611 imageinterlace( $dst_image );
1612 imagejpeg( $dst_image, $thumbPath, 95 );
1613 break;
1614 default:
1615 break;
1617 imagedestroy( $dst_image );
1618 imagedestroy( $src_image );
1623 # Check for zero-sized thumbnails. Those can be generated when
1624 # no disk space is available or some other error occurs
1626 $thumbstat = stat( $thumbPath );
1627 $imgstat = stat( $imgPath );
1628 if( $thumbstat["size"] == 0 )
1630 unlink( $thumbPath );
1634 return $thumbUrl;
1637 function makeThumbLinkObj( $nt, $label = "", $align = "right", $boxwidth = 180 ) {
1638 global $wgUploadPath, $wgLang;
1639 $name = $nt->getDBKey();
1640 $image = Title::makeTitle( Namespace::getImage(), $name );
1641 $url = wfImageUrl( $name );
1642 $path = wfImagePath( $name );
1644 #$label = htmlspecialchars( $label );
1645 $alt = preg_replace( "/<[^>]*>/", "", $label);
1646 $alt = htmlspecialchars( $alt );
1648 if ( file_exists( $path ) )
1650 list($width, $height, $type, $attr) = getimagesize( $path );
1651 } else {
1652 $width = $height = 200;
1654 $boxheight = intval( $height/($width/$boxwidth) );
1655 if ( $boxwidth > $width ) {
1656 $boxwidth = $width;
1657 $boxheight = $height;
1660 $thumbUrl = $this->createThumb( $name, $boxwidth );
1662 $u = $nt->escapeLocalURL();
1664 $more = htmlspecialchars( wfMsg( "thumbnail-more" ) );
1665 $magnifyalign = $wgLang->isRTL() ? "left" : "right";
1666 $textalign = $wgLang->isRTL() ? " style=\"text-align:right\"" : "";
1668 $s = "<div class=\"thumbnail-{$align}\" style=\"width:{$boxwidth}px;\">";
1669 if ( $thumbUrl == "" ) {
1670 $s .= str_replace( "$1", $name, wfMsg("missingimage") );
1671 } else {
1672 $s .= "\n".' <a href="'.$u.'" class="internal" title="'.$alt.'">'."\n".
1673 ' <img border="0" src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1674 ' width="'.$boxwidth.'" height="'.$boxheight.'" /></a>' ."\n".
1675 ' <a href="'.$u.'" class="internal" title="'.$more.'"> ' ."\n".
1676 ' <img border="0" src="'.$wgUploadPath.'/magnify-clip.png" ' .
1677 'width="26" height="24" align="'.$magnifyalign.'" alt="'.$more.'" /> </a>'."\n";
1679 $s .= ' <p'.$textalign.'>'.$label."</p>\n</div>";
1680 return $s;
1683 function makeMediaLink( $name, $url, $alt = "" ) {
1684 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1685 return $this->makeMediaLinkObj( $nt, $alt );
1688 function makeMediaLinkObj( $nt, $alt = "" )
1690 $name = $nt->getDBKey();
1691 $url = wfImageUrl( $name );
1692 if ( empty( $alt ) ) {
1693 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1696 $u = htmlspecialchars( $url );
1697 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1698 return $s;
1701 function specialLink( $name, $key = "" )
1703 global $wgLang;
1705 if ( "" == $key ) { $key = strtolower( $name ); }
1706 $pn = $wgLang->ucfirst( $name );
1707 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1708 wfMsg( $key ) );
1711 # Called by history lists and recent changes
1714 # Returns text for the start of the tabular part of RC
1715 function beginRecentChangesList()
1717 $this->rc_cache = array() ;
1718 $this->rcMoveIndex = 0;
1719 $this->rcCacheIndex = 0 ;
1720 $this->lastdate = "";
1721 return "";
1724 function beginImageHistoryList()
1726 $s = "\n<h2>" . wfMsg( "imghistory" ) . "</h2>\n" .
1727 "<p>" . wfMsg( "imghistlegend" ) . "\n<ul class='special'>";
1728 return $s;
1731 # Returns text for the end of RC
1732 # If enhanced RC is in use, returns pretty much all the text
1733 function endRecentChangesList()
1735 $s = $this->recentChangesBlock() ;
1736 $s .= "</ul>\n";
1737 return $s;
1740 # Enhanced RC ungrouped line
1741 function recentChangesBlockLine ( $rcObj )
1743 global $wgUploadPath, $wgLang ;
1745 # Get rc_xxxx variables
1746 extract( $rcObj->mAttribs ) ;
1747 $curIdEq = "curid=$rc_cur_id";
1749 # Spacer image
1750 $r = "" ;
1751 $r .= "<img src='{$wgUploadPath}/Arr_.png' width='12' height='12' border='0' />" ; $r .= "<tt>" ;
1753 if ( $rc_type == RC_MOVE ) {
1754 $r .= "&nbsp;&nbsp;";
1755 } else {
1756 # M & N (minor & new)
1757 $M = wfMsg( "minoreditletter" );
1758 $N = wfMsg( "newpageletter" );
1760 if ( $rc_type == RC_NEW ) {
1761 $r .= $N ;
1762 } else {
1763 $r .= "&nbsp;" ;
1765 if ( $rc_minor ) {
1766 $r .= $M ;
1767 } else {
1768 $r .= "&nbsp;" ;
1772 # Timestamp
1773 $r .= " ".$rcObj->timestamp." " ;
1774 $r .= "</tt>" ;
1776 # Article link
1777 $link = $rcObj->link ;
1778 if ( $rcObj->watched ) $link = "<strong>{$link}</strong>" ;
1779 $r .= $link ;
1781 # Cur
1782 $r .= " (" ;
1783 $r .= $rcObj->curlink ;
1784 $r .= "; " ;
1786 # Hist
1787 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( "hist" ), "{$curIdEq}&action=history" );
1789 # User/talk
1790 $r .= ") . . ".$rcObj->userlink ;
1791 $r .= $rcObj->usertalklink ;
1793 # Comment
1794 if ( $rc_comment != "" && $rc_type != RC_MOVE ) {
1795 $r .= $wgLang->emphasize( " (".wfEscapeHTML($rc_comment).")" );
1797 $r .= "<br>\n" ;
1798 return $r ;
1801 # Enhanced RC group
1802 function recentChangesBlockGroup ( $block )
1804 global $wgUploadPath, $wgLang ;
1806 $r = "" ;
1807 $M = wfMsg( "minoreditletter" );
1808 $N = wfMsg( "newpageletter" );
1810 # Collate list of users
1811 $isnew = false ;
1812 $userlinks = array () ;
1813 foreach ( $block AS $rcObj ) {
1814 $oldid = $rcObj->mAttribs['rc_last_oldid'];
1815 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
1816 $u = $rcObj->userlink ;
1817 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
1818 $userlinks[$u]++ ;
1821 # Sort the list and convert to text
1822 krsort ( $userlinks ) ;
1823 asort ( $userlinks ) ;
1824 $users = array () ;
1825 foreach ( $userlinks as $userlink => $count) {
1826 $text = $userlink ;
1827 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
1828 array_push ( $users , $text ) ;
1830 $users = " <font size='-1'>[".implode("; ",$users)."]</font>" ;
1832 # Arrow
1833 $rci = "RCI{$this->rcCacheIndex}" ;
1834 $rcl = "RCL{$this->rcCacheIndex}" ;
1835 $rcm = "RCM{$this->rcCacheIndex}" ;
1836 $toggleLink = "javascript:toggleVisibility(\"{$rci}\",\"{$rcm}\",\"{$rcl}\")" ;
1837 $arrowdir = $wgLang->isRTL() ? "l" : "r";
1838 $tl = "<span id='{$rcm}'><a href='$toggleLink'><img src='{$wgUploadPath}/Arr_{$arrowdir}.png' width='12' height='12' border='0' /></a></span>" ;
1839 $tl .= "<span id='{$rcl}' style='display:none'><a href='$toggleLink'><img src='{$wgUploadPath}/Arr_d.png' width='12' height='12' border='0' /></a></span>" ;
1840 $r .= $tl ;
1842 # Main line
1843 # M/N
1844 $r .= "<tt>" ;
1845 if ( $isnew ) $r .= $N ;
1846 else $r .= "&nbsp;" ;
1847 $r .= "&nbsp;" ; # Minor
1849 # Timestamp
1850 $r .= " ".$block[0]->timestamp." " ;
1851 $r .= "</tt>" ;
1853 # Article link
1854 $link = $block[0]->link ;
1855 if ( $block[0]->watched ) $link = "<strong>{$link}</strong>" ;
1856 $r .= $link ;
1858 $curIdEq = "curid=" . $block[0]->mAttribs['rc_cur_id'];
1859 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
1860 # Changes
1861 $r .= " (".count($block)." " ;
1862 if ( $isnew ) $r .= wfMsg("changes");
1863 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg("changes") ,
1864 "{$curIdEq}&diff=0&oldid=".$oldid ) ;
1865 $r .= "; " ;
1867 # History
1868 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( "history" ), "{$curIdEq}&action=history" );
1869 $r .= ")" ;
1872 $r .= $users ;
1873 $r .= "<br>\n" ;
1875 # Sub-entries
1876 $r .= "<div id='{$rci}' style='display:none'>" ;
1877 foreach ( $block AS $rcObj ) {
1878 # Get rc_xxxx variables
1879 extract( $rcObj->mAttribs );
1881 $r .= "<img src='{$wgUploadPath}/Arr_.png' width=12 height=12 border=0 />";
1882 $r .= "<tt>&nbsp; &nbsp; &nbsp; &nbsp;" ;
1883 if ( $rc_new ) $r .= $N ;
1884 else $r .= "&nbsp;" ;
1885 if ( $rc_minor ) $r .= $M ;
1886 else $r .= "&nbsp;" ;
1887 $r .= "</tt>" ;
1889 $o = "" ;
1890 if ( $rc_last_oldid != 0 ) {
1891 $o = "oldid=".$rc_last_oldid ;
1893 if ( $rc_type == RC_LOG ) {
1894 $link = $rcObj->timestamp ;
1895 } else {
1896 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
1898 $link = "<tt>{$link}</tt>" ;
1900 $r .= $link ;
1901 $r .= " (" ;
1902 $r .= $rcObj->curlink ;
1903 $r .= "; " ;
1904 $r .= $rcObj->lastlink ;
1905 $r .= ") . . ".$rcObj->userlink ;
1906 $r .= $rcObj->usertalklink ;
1907 if ( $rc_comment != "" ) {
1908 $r .= $wgLang->emphasize( " (".wfEscapeHTML($rc_comment).")" ) ;
1910 $r .= "<br>\n" ;
1912 $r .= "</div>\n" ;
1914 $this->rcCacheIndex++ ;
1915 return $r ;
1918 # If enhanced RC is in use, this function takes the previously cached
1919 # RC lines, arranges them, and outputs the HTML
1920 function recentChangesBlock ()
1922 global $wgUploadPath ;
1923 if ( count ( $this->rc_cache ) == 0 ) return "" ;
1924 $blockOut = "";
1925 foreach ( $this->rc_cache AS $secureName => $block ) {
1926 if ( count ( $block ) < 2 ) {
1927 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
1928 } else {
1929 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
1933 return "<div>{$blockOut}</div>" ;
1936 # Called in a loop over all displayed RC entries
1937 # Either returns the line, or caches it for later use
1938 function recentChangesLine( &$rc, $watched = false )
1940 global $wgUser ;
1941 $usenew = $wgUser->getOption( "usenewrc" );
1942 if ( $usenew )
1943 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
1944 else
1945 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
1946 return $line ;
1949 function recentChangesLineOld( &$rc, $watched = false )
1951 global $wgTitle, $wgLang, $wgUser;
1953 # Extract DB fields into local scope
1954 extract( $rc->mAttribs );
1955 $curIdEq = "curid=" . $rc_cur_id;
1957 # Make date header if necessary
1958 $date = $wgLang->date( $rc_timestamp, true);
1959 $s = "";
1960 if ( $date != $this->lastdate ) {
1961 if ( "" != $this->lastdate ) { $s .= "</ul>\n"; }
1962 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
1963 $this->lastdate = $date;
1965 $s .= "<li> ";
1967 if ( $rc_type == RC_MOVE ) {
1968 # Diff
1969 $s .= "(" . wfMsg( "diff" ) . ") (";
1970 # Hist
1971 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( "hist" ), "action=history" ) .
1972 ") . . ";
1974 # "[[x]] moved to [[y]]"
1976 $s .= wfMsg( "1movedto2", $this->makeKnownLinkObj( $rc->getTitle(), "", "redirect=no" ),
1977 $this->makeKnownLinkObj( $rc->getMovedToTitle(), "" ) );
1979 } else {
1980 # Diff link
1981 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
1982 $diffLink = wfMsg( "diff" );
1983 } else {
1984 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "diff" ),
1985 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}" );
1987 $s .= "($diffLink) (";
1989 # History link
1990 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "hist" ), "{$curIdEq}&action=history" );
1991 $s .= ") . . ";
1993 # M and N (minor and new)
1994 $M = wfMsg( "minoreditletter" );
1995 $N = wfMsg( "newpageletter" );
1996 if ( $rc_minor ) { $s .= " <strong>{$M}</strong>"; }
1997 if ( $rc_type == RC_NEW ) { $s .= "<strong>{$N}</strong>"; }
1999 # Article link
2000 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), "" );
2002 if ( $watched ) {
2003 $articleLink = "<strong>{$articleLink}</strong>";
2005 $s .= " $articleLink";
2009 # Timestamp
2010 $s .= "; " . $wgLang->time( $rc_timestamp, true ) . " . . ";
2012 # User link (or contributions for unregistered users)
2013 if ( 0 == $rc_user ) {
2014 $userLink = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
2015 $rc_user_text, "target=" . $rc_user_text );
2016 } else {
2017 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ":{$rc_user_text}", $rc_user_text );
2019 $s .= $userLink;
2021 # User talk link
2022 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2023 global $wgDisableAnonTalk;
2024 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2025 $userTalkLink = "";
2026 } else {
2027 $utns=$wgLang->getNsText(NS_USER_TALK);
2028 $userTalkLink= $this->makeLink($utns . ":{$rc_user_text}", $talkname );
2030 # Block link
2031 $blockLink="";
2032 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2033 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2034 "Blockip" ), wfMsg( "blocklink" ), "ip={$rc_user_text}" );
2037 if($blockLink) {
2038 if($userTalkLink) $userTalkLink .= " | ";
2039 $userTalkLink .= $blockLink;
2041 if($userTalkLink) $s.=" ({$userTalkLink})";
2043 # Add comment
2044 if ( "" != $rc_comment && "*" != $rc_comment && $rc_type != RC_MOVE ) {
2045 $s .= $wgLang->emphasize(" (" . wfEscapeHTML( $rc_comment ) . ")");
2047 $s .= "</li>\n";
2049 return $s;
2052 # function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
2053 function recentChangesLineNew( &$baseRC, $watched = false )
2055 global $wgTitle, $wgLang, $wgUser;
2057 # Create a specialised object
2058 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2060 # Extract fields from DB into the function scope (rc_xxxx variables)
2061 extract( $rc->mAttribs );
2062 $curIdEq = "curid=" . $rc_cur_id;
2064 # If it's a new day, add the headline and flush the cache
2065 $date = $wgLang->date( $rc_timestamp, true);
2066 $ret = "" ;
2067 if ( $date != $this->lastdate ) {
2068 # Process current cache
2069 $ret = $this->recentChangesBlock () ;
2070 $this->rc_cache = array() ;
2071 $ret .= "<h4>{$date}</h4>\n";
2072 $this->lastdate = $date;
2075 # Make article link
2076 if ( $rc_type == RC_MOVE ) {
2077 $clink = $this->makeKnownLinkObj( $rc->getTitle(), "", "redirect=no" );
2078 $clink .= " " . wfMsg("movedto") . " ";
2079 $clink .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), "" );
2080 } else {
2081 $clink = $this->makeKnownLinkObj( $rc->getTitle(), "" ) ;
2084 $time = $wgLang->time( $rc_timestamp, true );
2085 $rc->watched = $watched ;
2086 $rc->link = $clink ;
2087 $rc->timestamp = $time;
2089 # Make "cur" link
2090 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE) {
2091 $curLink = wfMsg( "cur" );
2092 } else {
2093 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "cur" ),
2094 "{$curIdEq}&diff=0&oldid={$rc_this_oldid}" );
2097 # Make "last" link
2098 $titleObj = $rc->getTitle();
2099 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE ) {
2100 $lastLink = wfMsg( "last" );
2101 } else {
2102 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( "last" ),
2103 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}" );
2106 # Make user link (or user contributions for unregistered users)
2107 if ( 0 == $rc_user ) {
2108 $userLink = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
2109 $rc_user_text, "target=" . $rc_user_text );
2110 } else {
2111 $userLink = $this->makeLink( $wgLang->getNsText(
2112 Namespace::getUser() ) . ":{$rc_user_text}", $rc_user_text );
2115 $rc->userlink = $userLink ;
2116 $rc->lastlink = $lastLink ;
2117 $rc->curlink = $curLink ;
2119 # Make user talk link
2120 $utns=$wgLang->getNsText(NS_USER_TALK);
2121 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2122 $userTalkLink= $this->makeLink($utns . ":{$rc_user_text}", $talkname );
2124 global $wgDisableAnonTalk;
2125 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2126 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2127 "Blockip" ), wfMsg( "blocklink" ), "ip={$rc_user_text}" );
2128 if( $wgDisableAnonTalk )
2129 $rc->usertalklink = " ({$blockLink})";
2130 else
2131 $rc->usertalklink = " ({$userTalkLink} | {$blockLink})";
2132 } else {
2133 if( $wgDisableAnonTalk && ($rc_user == 0) )
2134 $rc->usertalklink = "";
2135 else
2136 $rc->usertalklink = " ({$userTalkLink})";
2139 # Put accumulated information into the cache, for later display
2140 # Page moves go on their own line
2141 $title = $rc->getTitle();
2142 $secureName = $title->getPrefixedDBkey();
2143 if ( $rc_type == RC_MOVE ) {
2144 # Use an @ character to prevent collision with page names
2145 $this->rc_cache["@@" . ($this->rcMoveIndex++)] = array($rc);
2146 } else {
2147 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2148 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2150 return $ret;
2153 function endImageHistoryList()
2155 $s = "</ul>\n";
2156 return $s;
2159 function imageHistoryLine( $iscur, $ts, $img, $u, $ut, $size, $c )
2161 global $wgUser, $wgLang, $wgTitle;
2163 $dt = $wgLang->timeanddate( $ts, true );
2164 $del = wfMsg( "deleteimg" );
2165 $cur = wfMsg( "cur" );
2167 if ( $iscur ) {
2168 $url = wfImageUrl( $img );
2169 $rlink = $cur;
2170 if ( $wgUser->isSysop() ) {
2171 $link = $wgTitle->escapeLocalURL( "image=" . $wgTitle->getPartialURL() .
2172 "&action=delete" );
2173 $style = $this->getInternalLinkAttributes( $link, $del );
2175 $dlink = "<a href=\"{$link}\"{$style}>{$del}</a>";
2176 } else {
2177 $dlink = $del;
2179 } else {
2180 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
2181 if( $wgUser->getID() != 0 ) {
2182 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2183 wfMsg( "revertimg" ), "action=revert&oldimage=" .
2184 urlencode( $img ) );
2185 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2186 $del, "action=delete&oldimage=" . urlencode( $img ) );
2187 } else {
2188 # Having live active links for non-logged in users
2189 # means that bots and spiders crawling our site can
2190 # inadvertently change content. Baaaad idea.
2191 $rlink = wfMsg( "revertimg" );
2192 $dlink = $del;
2195 if ( 0 == $u ) { $ul = $ut; }
2196 else { $ul = $this->makeLink( $wgLang->getNsText(
2197 Namespace::getUser() ) . ":{$ut}", $ut ); }
2199 $nb = wfMsg( "nbytes", $size );
2200 $style = $this->getInternalLinkAttributes( $url, $dt );
2202 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$dt}</a>"
2203 . " . . {$ul} ({$nb})";
2205 if ( "" != $c && "*" != $c ) {
2206 $s .= $wgLang->emphasize(" (" . wfEscapeHTML( $c ) . ")");
2208 $s .= "</li>\n";
2209 return $s;
2212 function tocIndent($level) {
2213 return str_repeat( "<div class='tocindent'>\n", $level );
2216 function tocUnindent($level) {
2217 return str_repeat( "</div>\n", $level );
2220 # parameter level defines if we are on an indentation level
2221 function tocLine( $anchor, $tocline, $level ) {
2222 $link = "<a href=\"#$anchor\">$tocline</a><br />";
2223 if($level) {
2224 return "$link\n";
2225 } else {
2226 return "<div class='tocline'>$link</div>\n";
2231 function tocTable($toc) {
2232 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2233 # try min-width & co when somebody gets a chance
2234 $hideline = " <script type='text/javascript'>showTocToggle(\"" . addslashes( wfMsg("showtoc") ) . "\",\"" . addslashes( wfMsg("hidetoc") ) . "\")</script>";
2235 return
2236 "<p><table border=\"0\" id=\"toc\"><tr><td align=\"center\">\n".
2237 "<b>".wfMsg("toc")."</b>" .
2238 $hideline .
2239 "</td></tr><tr id='tocinside'><td>\n".
2240 $toc."</td></tr></table><P>\n";
2243 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2244 function editSectionScript( $section, $head ) {
2245 global $wgTitle, $wgRequest;
2246 if( $wgRequest->getInt( "oldid" ) && ( $wgRequest->getVal( "diff" ) != "0" ) ) {
2247 return $head;
2249 $url = $wgTitle->escapeLocalURL( "action=edit&section=$section" );
2250 return "<span oncontextmenu='document.location=\"$url\";return false;'>{$head}</span>";
2253 function editSectionLink( $section ) {
2254 global $wgRequest;
2255 global $wgTitle, $wgUser, $wgLang;
2257 if( $wgRequest->getInt( "oldid" ) && ( $wgRequest->getVal( "diff" ) != "0" ) ) {
2258 # Section edit links would be out of sync on an old page.
2259 # But, if we're diffing to the current page, they'll be
2260 # correct.
2261 return "";
2264 $editurl = "&section={$section}";
2265 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("editsection"),"action=edit".$editurl);
2267 if( $wgLang->isRTL() ) {
2268 $farside = "left";
2269 $nearside = "right";
2270 } else {
2271 $farside = "right";
2272 $nearside = "left";
2274 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2278 // This function is called by EditPage.php and shows a bulletin board style
2279 // toolbar for common editing functions. It can be disabled in the user preferences.
2280 // The necsesary JavaScript code can be found in style/wikibits.js.
2281 function getEditToolbar() {
2283 global $wgUploadPath,$wgLang;
2285 // toolarray an array of arrays which each include the filename of
2286 // the button image (without path), the opening tag, the closing tag,
2287 // and optionally a sample text that is inserted between the two when no
2288 // selection is highlighted.
2289 // The tip text is shown when the user moves the mouse over the button.
2290 $toolarray=array(
2291 array( "image"=>"button_bold.png",
2292 "open"=>"\'\'\'",
2293 "close"=>"\'\'\'",
2294 "sample"=>wfMsg("bold_sample"),
2295 "tip"=>wfMsg("bold_tip")),
2296 array( "image"=>"button_italic.png",
2297 "open"=>"\'\'",
2298 "close"=>"\'\'",
2299 "sample"=>wfMsg("italic_sample"),
2300 "tip"=>wfMsg("italic_tip")),
2301 array( "image"=>"button_link.png",
2302 "open"=>"[[",
2303 "close"=>"]]",
2304 "sample"=>wfMsg("link_sample"),
2305 "tip"=>wfMsg("link_tip")),
2306 array( "image"=>"button_extlink.png",
2307 "open"=>"[",
2308 "close"=>"]",
2309 "sample"=>wfMsg("extlink_sample"),
2310 "tip"=>wfMsg("extlink_tip")),
2311 array( "image"=>"button_headline.png",
2312 "open"=>"\\n== ",
2313 "close"=>" ==\\n",
2314 "sample"=>wfMsg("headline_sample"),
2315 "tip"=>wfMsg("headline_tip")),
2316 array( "image"=>"button_image.png",
2317 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2318 "close"=>"]]",
2319 "sample"=>wfMsg("image_sample"),
2320 "tip"=>wfMsg("image_tip")),
2321 array( "image"=>"button_media.png",
2322 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2323 "close"=>"]]",
2324 "sample"=>wfMsg("media_sample"),
2325 "tip"=>wfMsg("media_tip")),
2326 array( "image"=>"button_math.png",
2327 "open"=>"\\<math\\>",
2328 "close"=>"\\</math\\>",
2329 "sample"=>wfMsg("math_sample"),
2330 "tip"=>wfMsg("math_tip")),
2331 array( "image"=>"button_nowiki.png",
2332 "open"=>"\\<nowiki\\>",
2333 "close"=>"\\</nowiki\\>",
2334 "sample"=>wfMsg("nowiki_sample"),
2335 "tip"=>wfMsg("nowiki_tip")),
2336 array( "image"=>"button_sig.png",
2337 "open"=>"--~~~~",
2338 "close"=>"",
2339 "sample"=>"",
2340 "tip"=>wfMsg("sig_tip")),
2341 array( "image"=>"button_hr.png",
2342 "open"=>"\\n----\\n",
2343 "close"=>"",
2344 "sample"=>"",
2345 "tip"=>wfMsg("hr_tip"))
2347 $toolbar ="<script type='text/javascript'>\n";
2348 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2349 foreach($toolarray as $tool) {
2351 $image=$wgUploadPath."/".$tool["image"];
2352 $open=$tool["open"];
2353 $close=$tool["close"];
2354 $sample = addslashes( $tool["sample"] );
2356 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2357 // Older browsers show a "speedtip" type message only for ALT.
2358 // Ideally these should be different, realistically they
2359 // probably don't need to be.
2360 $tip = addslashes( $tool["tip"] );
2361 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2364 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "','" . addslashes(wfMsg("infobox_mozvote"))."');\n";
2365 $toolbar.="document.writeln(\"</div>\");\n</script>";
2366 return $toolbar;
2370 include_once( "SkinStandard.php" );
2371 include_once( "SkinNostalgia.php" );
2372 include_once( "SkinCologneBlue.php" );
2374 if( $wgUseSmarty ) {
2375 include_once( "SkinSmarty.php" );
2377 if( $wgUsePHPTal ) {
2378 include_once( "SkinPHPTal.php" );