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