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