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