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