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