Split off page history code to PageHistory.php out of Article.php and Skin.php.
[lhc/web/wiklou.git] / includes / Skin.php
1 <?
2 # See skin.doc
3
4 # These are the INTERNAL names, which get mapped
5 # directly to class names. For display purposes, the
6 # Language class has internationalized names
7 #
8 /* private */ $wgValidSkinNames = array(
9 "Standard", "Nostalgia", "CologneBlue" #, "Smarty", "Montparnasse"
10 );
11
12 # For some odd PHP bug, this function can't be part of a class
13 function getCategories ()
14 {
15 global $wgOut , $wgTitle , $wgUseCategoryMagic , $wgUser ;
16 if ( !isset ( $wgUseCategoryMagic ) || !$wgUseCategoryMagic ) return "" ;
17 if ( count ( $wgOut->mCategoryLinks ) == 0 ) return "" ;
18 if ( !$wgOut->isArticle() ) return "" ;
19 $sk = $wgUser->getSkin() ;
20 $s = "" ;
21 $s .= "\n<br>\n";
22 $s .= $sk->makeKnownLink ( "Special:Categories" , "Categories" , "article=".$wgTitle->getDBkey() ) ;
23 $t = implode ( " | " , $wgOut->mCategoryLinks ) ;
24 if ( $t != "" ) $s .= " : " ;
25 $s .= $t ;
26 return $s ;
27 }
28
29
30 class RecentChangesClass {
31 var $secureName , $displayName , $link , $namespace ;
32 var $oldid , $diffid , $timestamp , $curlink , $lastlink , $usertalklink , $versionlink ;
33 var $usercomment , $userlink ;
34 var $isminor , $isnew , $watched , $islog ;
35 } ;
36
37 class Skin {
38
39 /* private */ var $lastdate, $lastline;
40
41 var $rc_cache ; # Cache for Enhanced Recent Changes
42 var $rccc ; # Recent Changes Cache Counter for visibility toggle
43
44
45 function Skin()
46 {
47 }
48
49 function getSkinNames()
50 {
51 global $wgValidSkinNames;
52 return $wgValidSkinNames;
53 }
54
55 function getStylesheet()
56 {
57 return "wikistandard.css";
58 }
59
60 function qbSetting()
61 {
62 global $wgOut, $wgUser;
63
64 if ( $wgOut->isQuickbarSupressed() ) { return 0; }
65 $q = $wgUser->getOption( "quickbar" );
66 if ( "" == $q ) { $q = 0; }
67 return $q;
68 }
69
70 function initPage()
71 {
72 global $wgOut, $wgStyleSheetPath;
73 $fname = "Skin::initPage";
74 wfProfileIn( $fname );
75
76 $wgOut->addLink( "shortcut icon", "", "/favicon.ico" );
77 if ( $wgOut->isPrintable() ) { $ss = "wikiprintable.css"; }
78 else { $ss = $this->getStylesheet(); }
79 $wgOut->addLink( "stylesheet", "", "{$wgStyleSheetPath}/{$ss}" );
80 wfProfileOut( $fname );
81 }
82
83 function outputPage( &$out ) {
84 wfProfileIn( "Skin::outputPage" );
85 $this->initPage();
86 $out->out( $out->headElement() );
87
88 $out->out( "\n<body" );
89 $ops = $this->getBodyOptions();
90 foreach ( $ops as $name => $val ) {
91 $out->out( " $name='$val'" );
92 }
93 $out->out( ">\n" );
94 if ( $wgDebugComments ) {
95 $out->out( "<!-- Wiki debugging output:\n" .
96 $out->mDebugtext . "-->\n" );
97 }
98 $out->out( $this->beforeContent() );
99
100 $out->out( $out->mBodytext );
101
102 $out->out( $this->afterContent() );
103
104 wfProfileClose();
105 $out->out( $out->reportTime() );
106
107 $out->out( "\n</body></html>" );
108 }
109
110 function getHeadScripts() {
111 global $wgStyleSheetPath;
112 $r = "<script type=\"text/javascript\" src=\"{$wgStyleSheetPath}/wikibits.js\"></script>\n";
113 return $r;
114 }
115
116 function getUserStyles()
117 {
118 $s = "<style type='text/css'><!--\n";
119 $s .= $this->doGetUserStyles();
120 $s .= "//--></style>\n";
121 return $s;
122 }
123
124 function doGetUserStyles()
125 {
126 global $wgUser;
127
128 $s = "";
129 if ( 1 == $wgUser->getOption( "underline" ) ) {
130 # Don't override browser settings
131 } else {
132 # CHECK MERGE @@@
133 # Force no underline
134 $s .= "a.stub, a.new, a.internal, a.external { " .
135 "text-decoration: none; }\n";
136 }
137 if ( 1 == $wgUser->getOption( "highlightbroken" ) ) {
138 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
139 }
140 if ( 1 == $wgUser->getOption( "justify" ) ) {
141 $s .= "#article { text-align: justify; }\n";
142 }
143 return $s;
144 }
145
146 function getBodyOptions()
147 {
148 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $oldid, $redirect, $diff,$action;
149
150 if ( 0 != $wgTitle->getNamespace() ) {
151 $a = array( "bgcolor" => "#ffffec" );
152 }
153 else $a = array( "bgcolor" => "#FFFFFF" );
154 if($wgOut->isArticle() && $wgUser->getOption("editondblclick")
155 &&
156 (!$wgTitle->isProtected() || $wgUser->isSysop())
157
158 ) {
159 $n = $wgTitle->getPrefixedURL();
160 $t = wfMsg( "editthispage" );
161 $oid = $red = "";
162 if ( $redirect ) { $red = "&redirect={$redirect}"; }
163 if ( $oldid && ! isset( $diff ) ) {
164 $oid = "&oldid={$oldid}";
165 }
166 $s = wfLocalUrlE($n,"action=edit{$oid}{$red}");
167 $s = "document.location = \"" .$s ."\";";
168 $a += array ("ondblclick" => $s);
169
170 }
171 $a['onload'] = $wgOut->getOnloadHandler();
172 return $a;
173 }
174
175 function getExternalLinkAttributes( $link, $text )
176 {
177 global $wgUser, $wgOut, $wgLang;
178
179 $link = urldecode( $link );
180 $link = $wgLang->checkTitleEncoding( $link );
181 $link = str_replace( "_", " ", $link );
182 $link = wfEscapeHTML( $link );
183
184 if ( $wgOut->isPrintable() ) { $r = " class='printable'"; }
185 else { $r = " class='external'"; }
186
187 if ( 1 == $wgUser->getOption( "hover" ) ) {
188 $r .= " title=\"{$link}\"";
189 }
190 return $r;
191 }
192
193 function getInternalLinkAttributes( $link, $text, $broken = false )
194 {
195 global $wgUser, $wgOut;
196
197 $link = urldecode( $link );
198 $link = str_replace( "_", " ", $link );
199 $link = wfEscapeHTML( $link );
200
201 if ( $wgOut->isPrintable() ) {
202 $r = " class='printable'";
203 } else if ( $broken == "stub" ) {
204 $r = " class='stub'";
205 } else if ( $broken == "yes" ) {
206 $r = " class='new'";
207 } else {
208 $r = " class='internal'";
209 }
210
211 if ( 1 == $wgUser->getOption( "hover" ) ) {
212 $r .= " title=\"{$link}\"";
213 }
214 return $r;
215 }
216
217 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
218 {
219 global $wgUser, $wgOut;
220
221 if ( $wgOut->isPrintable() ) {
222 $r = " class='printable'";
223 } else if ( $broken == "stub" ) {
224 $r = " class='stub'";
225 } else if ( $broken == "yes" ) {
226 $r = " class='new'";
227 } else {
228 $r = " class='internal'";
229 }
230
231 if ( 1 == $wgUser->getOption( "hover" ) ) {
232 $r .= ' title ="' . $nt->getEscapedText() . '"';
233 }
234 return $r;
235 }
236
237 function getLogo()
238 {
239 global $wgLogo;
240 return $wgLogo;
241 }
242
243 # This will be called immediately after the <body> tag. Split into
244 # two functions to make it easier to subclass.
245 #
246 function beforeContent()
247 {
248 global $wgUser, $wgOut;
249
250 if ( $wgOut->isPrintable() ) {
251 $s = $this->pageTitle() . $this->pageSubtitle() . "\n";
252 $s .= "\n<div class='bodytext'>";
253 return $s;
254 }
255 return $this->doBeforeContent();
256 }
257
258 function doBeforeContent()
259 {
260 global $wgUser, $wgOut, $wgTitle, $wgLang;
261 $fname = "Skin::doBeforeContent";
262 wfProfileIn( $fname );
263
264 $s = "";
265 $qb = $this->qbSetting();
266
267 if( $langlinks = $this->otherLanguages() ) {
268 $rows = 2;
269 $borderhack = "";
270 } else {
271 $rows = 1;
272 $langlinks = false;
273 $borderhack = "class='top'";
274 }
275
276 $s .= "\n<div id='content'>\n<div id='topbar'>" .
277 "<table width='98%' border=0 cellspacing=0><tr>";
278
279 $shove = ($qb != 0);
280 $left = ($qb == 1 || $qb == 3);
281 if($wgLang->isRTL()) $left = !$left;
282
283 if ( !$shove ) {
284 $s .= "<td class='top' align=left valign=top rowspan='{$rows}'>" .
285 $this->logoText() . "</td>";
286 } elseif( $left ) {
287 $s .= $this->getQuickbarCompensator( $rows );
288 }
289 $l = $wgLang->isRTL() ? "right" : "left";
290 $s .= "<td {$borderhack} align='$l' valign='top'>";
291
292 $s .= $this->topLinks() ;
293 $s .= "<p class='subtitle'>" . $this->pageTitleLinks();
294
295 $r = $wgLang->isRTL() ? "left" : "right";
296 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap>";
297 $s .= $this->nameAndLogin();
298 $s .= "\n<br>" . $this->searchForm() . "</td>";
299
300 if ( $langlinks ) {
301 $s .= "</tr>\n<tr><td class='top' colspan=\"2\">$langlinks</td>";
302 }
303
304 if ( $shove && !$left ) { # Right
305 $s .= $this->getQuickbarCompensator( $rows );
306 }
307 $s .= "</tr></table>\n</div>\n";
308 $s .= "\n<div id='article'>";
309
310 $s .= $this->pageTitle();
311 $s .= $this->pageSubtitle() ;
312 $s .= getCategories(); // For some odd reason, zhis can't be a function of the object
313 $s .= "\n<p>";
314 wfProfileOut( $fname );
315 return $s;
316 }
317
318 function getQuickbarCompensator( $rows = 1 )
319 {
320 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
321 }
322
323 # This gets called immediately before the </body> tag.
324 #
325 function afterContent()
326 {
327 global $wgUser, $wgOut, $wgServer;
328 global $wgTitle;
329
330 if ( $wgOut->isPrintable() ) {
331 $s = "\n</div>\n";
332
333 $u = htmlspecialchars( $wgServer . $wgTitle->getFullURL() );
334 $u = "<a href=\"$u\">$u</a>";
335 $rf = wfMsg( "retrievedfrom", $u );
336
337 if ( $wgOut->isArticle() ) {
338 $lm = "<br>" . $this->lastModified();
339 } else { $lm = ""; }
340
341 $cr = wfMsg( "gnunote" );
342 $s .= "<p><em>{$rf}{$lm} {$cr}</em>\n";
343 return $s;
344 }
345 return $this->doAfterContent();
346 }
347
348 function doAfterContent()
349 {
350 global $wgUser, $wgOut, $wgLang;
351 $fname = "Skin::doAfterContent";
352 wfProfileIn( $fname );
353 wfProfileIn( "$fname-1" );
354
355 $s = "\n</div><br clear=all>\n";
356 $s .= "\n<div id='footer'>";
357 $s .= "<table width='98%' border=0 cellspacing=0><tr>";
358
359 wfProfileOut( "$fname-1" );
360 wfProfileIn( "$fname-2" );
361
362 $qb = $this->qbSetting();
363 $shove = ($qb != 0);
364 $left = ($qb == 1 || $qb == 3);
365 if($wgLang->isRTL()) $left = !$left;
366
367 if ( $shove && $left ) { # Left
368 $s .= $this->getQuickbarCompensator();
369 }
370 wfProfileOut( "$fname-2" );
371 wfProfileIn( "$fname-3" );
372 $l = $wgLang->isRTL() ? "right" : "left";
373 $s .= "<td class='bottom' align='$l' valign='top'>";
374
375 $s .= $this->bottomLinks();
376 $s .= "\n<br>" . $this->mainPageLink()
377 . " | " . $this->aboutLink()
378 . " | " . $this->specialLink( "recentchanges" )
379 . " | " . $this->searchForm()
380 . "<br>" . $this->pageStats();
381
382 $s .= "</td>";
383 if ( $shove && !$left ) { # Right
384 $s .= $this->getQuickbarCompensator();
385 }
386 $s .= "</tr></table>\n</div>\n</div>\n";
387
388 wfProfileOut( "$fname-3" );
389 wfProfileIn( "$fname-4" );
390 if ( 0 != $qb ) { $s .= $this->quickBar(); }
391 wfProfileOut( "$fname-4" );
392 wfProfileOut( $fname );
393 return $s;
394 }
395
396 function pageTitleLinks()
397 {
398 global $wgOut, $wgTitle, $oldid, $action, $diff, $wgUser, $wgLang, $wgUseApproval ;
399
400 $s = $this->printableLink();
401
402 if ( $wgOut->isArticle() ) {
403 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
404 $name = $wgTitle->getDBkey();
405 $link = wfEscapeHTML( wfImageUrl( $name ) );
406 $style = $this->getInternalLinkAttributes( $link, $name );
407 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
408 }
409 # This will show the "Approve" link if $wgUseApproval=true;
410 if ( isset ( $wgUseApproval ) && $wgUseApproval )
411 {
412 $t = $wgTitle->getDBkey();
413 $name = "Approve this article" ;
414 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
415 #wfEscapeHTML( wfImageUrl( $name ) );
416 $style = $this->getExternalLinkAttributes( $link, $name );
417 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
418 } }
419 if ( "history" == $action || isset( $diff ) || isset( $oldid ) ) {
420 $s .= " | " . $this->makeKnownLink( $wgTitle->getPrefixedText(),
421 wfMsg( "currentrev" ) );
422 }
423
424 if ( $wgUser->getNewtalk() ) {
425 # do not show "You have new messages" text when we are viewing our
426 # own talk page
427
428 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
429 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
430 $n =$wgUser->getName();
431 $tl = $this->makeKnownLink( $wgLang->getNsText(
432 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
433 wfMsg("newmessageslink") );
434 $s.=" | <strong>". wfMsg( "newmessages", $tl ) . "</strong>";
435 }
436 }
437 if( $wgUser->isSysop() &&
438 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
439 ($n = $wgTitle->isDeleted() ) ) {
440 $s .= " | " . wfMsg( "thisisdeleted",
441 $this->makeKnownLink(
442 $wgLang->SpecialPage( "Undelete/" . $wgTitle->getPrefixedDBkey() ),
443 wfMsg( "restorelink", $n ) ) );
444 }
445 return $s;
446 }
447
448 function printableLink()
449 {
450 global $wgOut, $wgTitle, $oldid, $action;
451
452 $q = "";
453 foreach( $_GET as $var => $val ) {
454 if( $var != "title" && $var != "printable" )
455 $q .= urlencode( $var ) . "=" . urlencode( $val );
456 }
457 if( !empty( $q ) ) $q .= "&";
458
459 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
460 WfMsg( "printableversion" ), "{$q}printable=yes" );
461 return $s;
462 }
463
464 function pageTitle()
465 {
466 global $wgOut, $wgTitle, $wgUser;
467
468 $s = "<h1 class='pagetitle'>" . $wgOut->getPageTitle() . "</h1>";
469 if($wgUser->getOption("editsectiononrightclick") && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
470 return $s;
471 }
472
473 function pageSubtitle()
474 {
475 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
476
477 $sub = $wgOut->getSubtitle();
478 if ( "" == $sub ) {
479 global $wgExtraSubtitle;
480 $sub = wfMsg( "fromwikipedia" ) . $wgExtraSubtitle;
481 }
482 if($wgOut->isArticle() && $wgNamespacesWithSubpages[$wgTitle->getNamespace()]) {
483 $ptext=$wgTitle->getPrefixedText();
484 if(preg_match("/\//",$ptext)) {
485 $sub.="</p><p class='subpages'>";
486 $links=explode("/",$ptext);
487 $c=0;
488 $growinglink="";
489 foreach($links as $link) {
490 $c++;
491 if ($c<count($links)) {
492 $growinglink .= $link;
493 $getlink = $this->makeLink( $growinglink, $link );
494 if(preg_match("/class='new'/i",$getlink)) { break; } # this is a hack, but it saves time
495 if ($c>1) {
496 $sub .= " | ";
497 } else {
498 $sub .="&lt; ";
499 }
500 $sub .= $getlink;
501 $growinglink.="/";
502 }
503
504 }
505 }
506 }
507 $s = "<p class='subtitle'>{$sub}\n";
508 return $s;
509 }
510
511 function nameAndLogin()
512 {
513 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader;
514
515 $li = $wgLang->specialPage( "Userlogin" );
516 $lo = $wgLang->specialPage( "Userlogout" );
517
518 $s = "";
519 if ( 0 == $wgUser->getID() ) {
520 if( $wgShowIPinHeader ) {
521 $n = getenv( "REMOTE_ADDR" );
522
523 $tl = $this->makeKnownLink( $wgLang->getNsText(
524 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
525 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
526
527 $s .= $n . " (".$tl.")";
528 } else {
529 $s .= wfMsg("notloggedin");
530 }
531
532 $rt = $wgTitle->getPrefixedURL();
533 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
534 $q = "";
535 } else { $q = "returnto={$rt}"; }
536
537 $s .= "\n<br>" . $this->makeKnownLink( $li,
538 wfMsg( "login" ), $q );
539 } else {
540 $n = $wgUser->getName();
541 $rt = $wgTitle->getPrefixedURL();
542 $tl = $this->makeKnownLink( $wgLang->getNsText(
543 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
544 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
545
546 $tl = " ({$tl})";
547
548 $s .= $this->makeKnownLink( $wgLang->getNsText(
549 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br>" .
550 $this->makeKnownLink( $lo, wfMsg( "logout" ),
551 "returnto={$rt}" ) . " | " .
552 $this->specialLink( "preferences" );
553 }
554 $s .= " | " . $this->makeKnownLink( wfMsg( "helppage" ),
555 wfMsg( "help" ) );
556
557 return $s;
558 }
559
560 function searchForm()
561 {
562 global $search;
563
564 $s = "<form name='search' class='inline' method=get action=\""
565 . wfLocalUrl( "" ) . "\">"
566 . "<input type=text name=\"search\" size=19 value=\""
567 . htmlspecialchars(substr($search,0,256)) . "\">\n"
568 . "<input type=submit name=\"go\" value=\"" . wfMsg ("go") . "\">&nbsp;"
569 . "<input type=submit value=\"" . wfMsg ("search") . "\"></form>";
570
571 return $s;
572 }
573
574 function topLinks()
575 {
576 global $wgOut;
577 $sep = " |\n";
578
579 $s = $this->mainPageLink() . $sep
580 . $this->specialLink( "recentchanges" );
581
582 if ( $wgOut->isArticle() ) {
583 $s .= $sep . $this->editThisPage()
584 . $sep . $this->historyLink();
585 }
586 # Many people don't like this dropdown box
587 #$s .= $sep . $this->specialPagesList();
588
589 return $s;
590 }
591
592 function bottomLinks()
593 {
594 global $wgOut, $wgUser, $wgTitle;
595 $sep = " |\n";
596
597 $s = "";
598 if ( $wgOut->isArticle() ) {
599 $s .= "<strong>" . $this->editThisPage() . "</strong>";
600 if ( 0 != $wgUser->getID() ) {
601 $s .= $sep . $this->watchThisPage();
602 }
603 $s .= $sep . $this->talkLink()
604 . $sep . $this->historyLink()
605 . $sep . $this->whatLinksHere()
606 . $sep . $this->watchPageLinksLink();
607
608 if ( $wgTitle->getNamespace() == Namespace::getUser()
609 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
610
611 {
612 $id=User::idFromName($wgTitle->getText());
613 $ip=User::isIP($wgTitle->getText());
614
615 if($id || $ip) { # both anons and non-anons have contri list
616 $s .= $sep . $this->userContribsLink();
617 }
618 if ( 0 != $wgUser->getID() ) { # show only to signed in users
619 if($id) { # can only email non-anons
620 $s .= $sep . $this->emailUserLink();
621 }
622 }
623 }
624 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
625 $s .= "\n<br>" . $this->deleteThisPage() .
626 $sep . $this->protectThisPage() .
627 $sep . $this->moveThisPage();
628 }
629 $s .= "<br>\n" . $this->otherLanguages();
630 }
631 return $s;
632 }
633
634 function pageStats()
635 {
636 global $wgOut, $wgLang, $wgArticle;
637 global $oldid, $diff, $wgDisableCounters;
638
639 if ( ! $wgOut->isArticle() ) { return ""; }
640 if ( isset( $oldid ) || isset( $diff ) ) { return ""; }
641 if ( 0 == $wgArticle->getID() ) { return ""; }
642
643 if ( $wgDisableCounters ) {
644 $s = "";
645 } else {
646 $count = $wgArticle->getCount();
647 $s = wfMsg( "viewcount", $count );
648 }
649 $s .= $this->lastModified();
650 $s .= " " . wfMsg( "gnunote" );
651 return "<span id='pagestats'>{$s}</span>";
652 }
653
654 function lastModified()
655 {
656 global $wgLang, $wgArticle;
657
658 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
659 $s = " " . wfMsg( "lastmodified", $d );
660 return $s;
661 }
662
663 function logoText( $align = "" )
664 {
665 if ( "" != $align ) { $a = " align='{$align}'"; }
666 else { $a = ""; }
667
668 $mp = wfMsg( "mainpage" );
669 $s = "<a href=\"" . wfLocalUrlE( urlencode( $mp ) )
670 . "\"><img{$a} border=0 src=\""
671 . $this->getLogo() . "\" alt=\"" . "[{$mp}]\"></a>";
672 return $s;
673 }
674
675 function quickBar()
676 {
677 global $wgOut, $wgTitle, $wgUser, $action, $wgLang;
678 global $wpPreview, $wgDisableUploads;
679
680 $fname = "Skin::quickBar";
681 wfProfileIn( $fname );
682
683 $tns=$wgTitle->getNamespace();
684
685 $s = "\n<div id='quickbar'>";
686 $s .= "\n" . $this->logoText() . "\n<hr class='sep'>";
687
688 $sep = "\n<br>";
689 $s .= $this->mainPageLink()
690 . $sep . $this->specialLink( "recentchanges" )
691 . $sep . $this->specialLink( "randompage" );
692 if ($wgUser->getID()) {
693 $s.= $sep . $this->specialLink( "watchlist" ) ;
694 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
695 wfMsg( "mycontris" ), "target=" . wfUrlencode($wgUser->getName() ) );
696
697 }
698 // only show watchlist link if logged in
699 if ( wfMsg ( "currentevents" ) != "-" ) $s .= $sep . $this->makeKnownLink( wfMsg( "currentevents" ), "" ) ;
700 $s .= "\n<br><hr class='sep'>";
701 $articleExists = $wgTitle->getArticleId();
702 if ( $wgOut->isArticle() || $action =="edit" || $action =="history" || $wpPreview) {
703 if($wgOut->isArticle()) {
704 $s .= "<strong>" . $this->editThisPage() . "</strong>";
705 } else { # backlink to the article in edit or history mode
706 if($articleExists){ # no backlink if no article
707 switch($tns) {
708 case 0:
709 $text = wfMsg("articlepage");
710 break;
711 case 1:
712 $text = wfMsg("viewtalkpage");
713 break;
714 case 2:
715 $text = wfMsg("userpage");
716 break;
717 case 3:
718 $text = wfMsg("viewtalkpage");
719 break;
720 case 4:
721 $text = wfMsg("wikipediapage");
722 break;
723 case 5:
724 $text = wfMsg("viewtalkpage");
725 break;
726 case 6:
727 $text = wfMsg("imagepage");
728 break;
729 case 7:
730 $text = wfMsg("viewtalkpage");
731 break;
732 default:
733 $text= wfMsg("articlepage");
734 }
735
736 $link = $wgTitle->getText();
737 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
738 $link = $nstext . ":" . $link ;
739 }
740
741 $s .= $this->makeLink( $link, $text );
742 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
743 # we just throw in a "New page" text to tell the user that he's in edit mode,
744 # and to avoid messing with the separator that is prepended to the next item
745 $s .= "<strong>" . wfMsg("newpage") . "</strong>";
746 }
747
748 }
749
750
751 if( $tns%2 && $action!="edit" && !$wpPreview) {
752 $s.="<br>".$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("postcomment"),"action=edit&section=new");
753 }
754
755 /*
756 watching could cause problems in edit mode:
757 if user edits article, then loads "watch this article" in background and then saves
758 article with "Watch this article" checkbox disabled, the article is transparently
759 unwatched. Therefore we do not show the "Watch this page" link in edit mode
760 */
761 if ( 0 != $wgUser->getID() && $articleExists) {
762 if($action!="edit" && $action!="history" &&
763 $action != "submit" )
764 {
765 $s .= $sep . $this->watchThisPage();
766 }
767 if ( $wgTitle->userCanEdit() )
768 $s .= $sep . $this->moveThisPage();
769 }
770 if ( $wgUser->isSysop() and $articleExists ) {
771 $s .= $sep . $this->deleteThisPage() .
772 $sep . $this->protectThisPage();
773 }
774 $s .= $sep . $this->talkLink();
775 if ($articleExists && $action !="history") {
776 $s .= $sep . $this->historyLink();
777 }
778 $s.=$sep . $this->whatLinksHere();
779
780 if($wgOut->isArticle()) {
781 $s .= $sep . $this->watchPageLinksLink();
782 }
783
784 if ( Namespace::getUser() == $wgTitle->getNamespace()
785 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
786 ) {
787
788 $id=User::idFromName($wgTitle->getText());
789 $ip=User::isIP($wgTitle->getText());
790
791 if($id||$ip) {
792 $s .= $sep . $this->userContribsLink();
793 }
794 if ( 0 != $wgUser->getID() ) {
795 if($id) { # can only email real users
796 $s .= $sep . $this->emailUserLink();
797 }
798 }
799 }
800 $s .= "\n<br><hr class='sep'>";
801 }
802
803 if ( 0 != $wgUser->getID() && !$wgDisableUploads ) {
804 $s .= $this->specialLink( "upload" ) . $sep;
805 }
806 $s .= $this->specialLink( "specialpages" )
807 . $sep . $this->bugReportsLink();
808
809 global $wgSiteSupportPage;
810 if( $wgSiteSupportPage ) {
811 $s .= "\n<br><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
812 "\" class=\"internal\">" . wfMsg( "sitesupport" ) . "</a>";
813 }
814
815 $s .= "\n<br></div>\n";
816 wfProfileOut( $fname );
817 return $s;
818 }
819
820 function specialPagesList()
821 {
822 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
823 $a = array();
824
825 $validSP = $wgLang->getValidSpecialPages();
826
827 foreach ( $validSP as $name => $desc ) {
828 if ( "" == $desc ) { continue; }
829 $a[$name] = $desc;
830 }
831 if ( $wgUser->isSysop() )
832 {
833 $sysopSP = $wgLang->getSysopSpecialPages();
834
835 foreach ( $sysopSP as $name => $desc ) {
836 if ( "" == $desc ) { continue; }
837 $a[$name] = $desc ;
838 }
839 }
840 if ( $wgUser->isDeveloper() )
841 {
842 $devSP = $wgLang->getDeveloperSpecialPages();
843
844 foreach ( $devSP as $name => $desc ) {
845 if ( "" == $desc ) { continue; }
846 $a[$name] = $desc ;
847 }
848 }
849 $go = wfMsg( "go" );
850 $sp = wfMsg( "specialpages" );
851 $spp = $wgLang->specialPage( "Specialpages" );
852
853 $s = "<form id=\"specialpages\" method=\"get\" class=\"inline\" " .
854 "action=\"{$wgServer}{$wgRedirectScript}\">\n";
855 $s .= "<select name=\"wpDropdown\">\n";
856 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
857
858 foreach ( $a as $name => $desc ) {
859 $p = $wgLang->specialPage( $name );
860 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
861 }
862 $s .= "</select>\n";
863 $s .= "<input type=submit value=\"{$go}\" name=redirect>\n";
864 $s .= "</form>\n";
865 return $s;
866 }
867
868 function mainPageLink()
869 {
870 $mp = wfMsg( "mainpage" );
871 $s = $this->makeKnownLink( $mp, $mp );
872 return $s;
873 }
874
875 function copyrightLink()
876 {
877 $s = $this->makeKnownLink( wfMsg( "copyrightpage" ),
878 wfMsg( "copyrightpagename" ) );
879 return $s;
880 }
881
882 function aboutLink()
883 {
884 $s = $this->makeKnownLink( wfMsg( "aboutpage" ),
885 wfMsg( "aboutwikipedia" ) );
886 return $s;
887 }
888
889 function editThisPage()
890 {
891 global $wgOut, $wgTitle, $oldid, $redirect, $diff;
892
893 if ( ! $wgOut->isArticle() || $diff ) {
894 $s = wfMsg( "protectedpage" );
895 } else if ( $wgTitle->userCanEdit() ) {
896 $n = $wgTitle->getPrefixedText();
897 $t = wfMsg( "editthispage" );
898 $oid = $red = "";
899
900 if ( $redirect ) { $red = "&redirect={$redirect}"; }
901 if ( $oldid && ! isset( $diff ) ) {
902 $oid = "&oldid={$oldid}";
903 }
904 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
905 } else {
906 $s = wfMsg( "protectedpage" );
907 }
908 return $s;
909 }
910
911 function deleteThisPage()
912 {
913 global $wgUser, $wgOut, $wgTitle, $diff;
914
915 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
916 $n = $wgTitle->getPrefixedText();
917 $t = wfMsg( "deletethispage" );
918
919 $s = $this->makeKnownLink( $n, $t, "action=delete" );
920 } else {
921 $s = "";
922 }
923 return $s;
924 }
925
926 function protectThisPage()
927 {
928 global $wgUser, $wgOut, $wgTitle, $diff;
929
930 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
931 $n = $wgTitle->getPrefixedText();
932
933 if ( $wgTitle->isProtected() ) {
934 $t = wfMsg( "unprotectthispage" );
935 $q = "action=unprotect";
936 } else {
937 $t = wfMsg( "protectthispage" );
938 $q = "action=protect";
939 }
940 $s = $this->makeKnownLink( $n, $t, $q );
941 } else {
942 $s = "";
943 }
944 return $s;
945 }
946
947 function watchThisPage()
948 {
949 global $wgUser, $wgOut, $wgTitle, $diff;
950
951 if ( $wgOut->isArticle() && ( ! $diff ) ) {
952 $n = $wgTitle->getPrefixedText();
953
954 if ( $wgTitle->userIsWatching() ) {
955 $t = wfMsg( "unwatchthispage" );
956 $q = "action=unwatch";
957 } else {
958 $t = wfMsg( "watchthispage" );
959 $q = "action=watch";
960 }
961 $s = $this->makeKnownLink( $n, $t, $q );
962 } else {
963 $s = wfMsg( "notanarticle" );
964 }
965 return $s;
966 }
967
968 function moveThisPage()
969 {
970 global $wgTitle, $wgLang;
971
972 if ( $wgTitle->userCanEdit() ) {
973 $s = $this->makeKnownLink( $wgLang->specialPage( "Movepage" ),
974 wfMsg( "movethispage" ), "target=" . $wgTitle->getPrefixedURL() );
975 } // no message if page is protected - would be redundant
976 return $s;
977 }
978
979 function historyLink()
980 {
981 global $wgTitle;
982
983 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
984 wfMsg( "history" ), "action=history" );
985 return $s;
986 }
987
988 function whatLinksHere()
989 {
990 global $wgTitle, $wgLang;
991
992 $s = $this->makeKnownLink( $wgLang->specialPage( "Whatlinkshere" ),
993 wfMsg( "whatlinkshere" ), "target=" . $wgTitle->getPrefixedURL() );
994 return $s;
995 }
996
997 function userContribsLink()
998 {
999 global $wgTitle, $wgLang;
1000
1001 $s = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1002 wfMsg( "contributions" ), "target=" . $wgTitle->getURL() );
1003 return $s;
1004 }
1005
1006 function emailUserLink()
1007 {
1008 global $wgTitle, $wgLang;
1009
1010 $s = $this->makeKnownLink( $wgLang->specialPage( "Emailuser" ),
1011 wfMsg( "emailuser" ), "target=" . $wgTitle->getURL() );
1012 return $s;
1013 }
1014
1015 function watchPageLinksLink()
1016 {
1017 global $wgOut, $wgTitle, $wgLang;
1018
1019 if ( ! $wgOut->isArticle() ) {
1020 $s = "(" . wfMsg( "notanarticle" ) . ")";
1021 } else {
1022 $s = $this->makeKnownLink( $wgLang->specialPage(
1023 "Recentchangeslinked" ), wfMsg( "recentchangeslinked" ),
1024 "target=" . $wgTitle->getPrefixedURL() );
1025 }
1026 return $s;
1027 }
1028
1029 function otherLanguages()
1030 {
1031 global $wgOut, $wgLang, $wgTitle;
1032
1033 $a = $wgOut->getLanguageLinks();
1034 # TEST THIS @@@
1035 if ( 0 == count( $a ) ) {
1036 if ( !$wgUseNewInterlanguage ) return "";
1037 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1038 if ( $ns != 0 AND $ns != 1 ) return "" ;
1039 $pn = "Intl" ;
1040 $x = "mode=addlink&xt=".$wgTitle->getDBkey() ;
1041 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1042 wfMsg( "intl" ) , $x );
1043 }
1044
1045 if ( !$wgUseNewInterlanguage ) {
1046 $s = wfMsg( "otherlanguages" ) . ": ";
1047 } else {
1048 global $wgLanguageCode ;
1049 $x = "mode=zoom&xt=".$wgTitle->getDBkey() ;
1050 $x .= "&xl=".$wgLanguageCode ;
1051 $s = $this->makeKnownLink( $wgLang->specialPage( "Intl" ),
1052 wfMsg( "otherlanguages" ) , $x ) . ": " ;
1053 }
1054
1055 $s = wfMsg( "otherlanguages" ) . ": ";
1056 $first = true;
1057 if($wgLang->isRTL()) $s .= "<span dir='LTR'>";
1058 foreach( $a as $l ) {
1059 if ( ! $first ) { $s .= " | "; }
1060 $first = false;
1061
1062 $nt = Title::newFromText( $l );
1063 $url = $nt->getFullURL();
1064 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1065
1066 if ( "" == $text ) { $text = $l; }
1067 $style = $this->getExternalLinkAttributes( $l, $text );
1068 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1069 }
1070 if($wgLang->isRTL()) $s .= "</span>";
1071 return $s;
1072 }
1073
1074 function bugReportsLink()
1075 {
1076 $s = $this->makeKnownLink( wfMsg( "bugreportspage" ),
1077 wfMsg( "bugreports" ) );
1078 return $s;
1079 }
1080
1081 function dateLink()
1082 {
1083 global $wgLinkCache;
1084 $t1 = Title::newFromText( gmdate( "F j" ) );
1085 $t2 = Title::newFromText( gmdate( "Y" ) );
1086
1087 $wgLinkCache->suspend();
1088 $id = $t1->getArticleID();
1089 $wgLinkCache->resume();
1090
1091 if ( 0 == $id ) {
1092 $s = $this->makeBrokenLink( $t1->getText() );
1093 } else {
1094 $s = $this->makeKnownLink( $t1->getText() );
1095 }
1096 $s .= ", ";
1097
1098 $wgLinkCache->suspend();
1099 $id = $t2->getArticleID();
1100 $wgLinkCache->resume();
1101
1102 if ( 0 == $id ) {
1103 $s .= $this->makeBrokenLink( $t2->getText() );
1104 } else {
1105 $s .= $this->makeKnownLink( $t2->getText() );
1106 }
1107 return $s;
1108 }
1109
1110 function talkLink()
1111 {
1112 global $wgLang, $wgTitle, $wgLinkCache;
1113
1114 $tns = $wgTitle->getNamespace();
1115 if ( -1 == $tns ) { return ""; }
1116
1117 $pn = $wgTitle->getText();
1118 $tp = wfMsg( "talkpage" );
1119 if ( Namespace::isTalk( $tns ) ) {
1120 $lns = Namespace::getSubject( $tns );
1121 switch($tns) {
1122 case 1:
1123 $text = wfMsg("articlepage");
1124 break;
1125 case 3:
1126 $text = wfMsg("userpage");
1127 break;
1128 case 5:
1129 $text = wfMsg("wikipediapage");
1130 break;
1131 case 7:
1132 $text = wfMsg("imagepage");
1133 break;
1134 default:
1135 $text= wfMsg("articlepage");
1136 }
1137 } else {
1138
1139 $lns = Namespace::getTalk( $tns );
1140 $text=$tp;
1141 }
1142 $n = $wgLang->getNsText( $lns );
1143 if ( "" == $n ) { $link = $pn; }
1144 else { $link = "{$n}:{$pn}"; }
1145
1146 $wgLinkCache->suspend();
1147 $s = $this->makeLink( $link, $text );
1148 $wgLinkCache->resume();
1149
1150 return $s;
1151 }
1152
1153 function commentLink()
1154 {
1155 global $wgLang, $wgTitle, $wgLinkCache;
1156
1157 $tns = $wgTitle->getNamespace();
1158 if ( -1 == $tns ) { return ""; }
1159
1160 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1161
1162 # assert Namespace::isTalk( $lns )
1163
1164 $n = $wgLang->getNsText( $lns );
1165 $pn = $wgTitle->getText();
1166
1167 $link = "{$n}:{$pn}";
1168
1169 $wgLinkCache->suspend();
1170 $s = $this->makeKnownLink($link, wfMsg("postcomment"), "action=edit&section=new");
1171 $wgLinkCache->resume();
1172
1173 return $s;
1174 }
1175
1176 # After all the page content is transformed into HTML, it makes
1177 # a final pass through here for things like table backgrounds.
1178 #
1179 function transformContent( $text )
1180 {
1181 return $text;
1182 }
1183
1184 # Note: This function MUST call getArticleID() on the link,
1185 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1186 #
1187 function makeLink( $title, $text = "", $query = "", $trail = "" ) {
1188 wfProfileIn( "Skin::makeLink" );
1189 $nt = Title::newFromText( $title );
1190 if ($nt) {
1191 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1192 } else {
1193 wfDebug( "Invalid title passed to Skin::makeLink(): \"$title\"\n" );
1194 $result = $text == "" ? $title : $text;
1195 }
1196
1197 wfProfileOut( "Skin::makeLink" );
1198 return $result;
1199 }
1200
1201 function makeKnownLink( $title, $text = "", $query = "", $trail = "" ) {
1202 $nt = Title::newFromText( $title );
1203 if ($nt) {
1204 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1205 } else {
1206 wfDebug( "Invalid title passed to Skin::makeKnownLink(): \"$title\"\n" );
1207 return $text == "" ? $title : $text;
1208 }
1209 }
1210
1211 function makeBrokenLink( $title, $text = "", $query = "", $trail = "" ) {
1212 $nt = Title::newFromText( $title );
1213 if ($nt) {
1214 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1215 } else {
1216 wfDebug( "Invalid title passed to Skin::makeBrokenLink(): \"$title\"\n" );
1217 return $text == "" ? $title : $text;
1218 }
1219 }
1220
1221 function makeStubLink( $title, $text = "", $query = "", $trail = "" ) {
1222 $nt = Title::newFromText( $title );
1223 if ($nt) {
1224 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1225 } else {
1226 wfDebug( "Invalid title passed to Skin::makeStubLink(): \"$title\"\n" );
1227 return $text == "" ? $title : $text;
1228 }
1229 }
1230
1231 # Pass a title object, not a title string
1232 function makeLinkObj( &$nt, $text= "", $query = "", $trail = "" )
1233 {
1234 global $wgOut, $wgUser;
1235 if ( $nt->isExternal() ) {
1236 $u = $nt->getFullURL();
1237 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1238 $style = $this->getExternalLinkAttributes( $link, $text );
1239
1240 $inside = "";
1241 if ( "" != $trail ) {
1242 if ( preg_match( "/^([a-z]+)(.*)$$/sD", $trail, $m ) ) {
1243 $inside = $m[1];
1244 $trail = $m[2];
1245 }
1246 }
1247 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1248 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1249 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
1250 } elseif ( ( -1 == $nt->getNamespace() ) ||
1251 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1252 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
1253 } else {
1254 $aid = $nt->getArticleID() ;
1255 if ( 0 == $aid ) {
1256 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail );
1257 } else {
1258 $threshold = $wgUser->getOption("stubthreshold") ;
1259 if ( $threshold > 0 ) {
1260 $res = wfQuery ( "SELECT HIGH_PRIORITY length(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ ) ;
1261
1262 if ( wfNumRows( $res ) > 0 ) {
1263 $s = wfFetchObject( $res );
1264 $size = $s->x;
1265 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1266 $size = $threshold*2 ; # Really big
1267 }
1268 wfFreeResult( $res );
1269 } else {
1270 $size = $threshold*2 ; # Really big
1271 }
1272 } else {
1273 $size = 1 ;
1274 }
1275 if ( $size < $threshold ) {
1276 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail );
1277 } else {
1278 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail );
1279 }
1280 }
1281 }
1282 return $retVal;
1283 }
1284
1285 # Pass a title object, not a title string
1286 function makeKnownLinkObj( &$nt, $text = "", $query = "", $trail = "" )
1287 {
1288 global $wgOut, $wgTitle;
1289
1290 $fname = "Skin::makeKnownLinkObj";
1291 wfProfileIn( $fname );
1292
1293 $link = $nt->getPrefixedURL();
1294
1295 if ( "" == $link ) {
1296 $u = "";
1297 if ( "" == $text ) { $text = $nt->getFragment(); }
1298 } else {
1299 $u = wfLocalUrlE( $link, $query );
1300 }
1301 if ( "" != $nt->getFragment() ) {
1302 $u .= "#" . wfEscapeHTML( $nt->getFragment() );
1303 }
1304 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1305 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1306
1307 $inside = "";
1308 if ( "" != $trail ) {
1309 if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
1310 $inside = $m[1];
1311 $trail = $m[2];
1312 }
1313 }
1314 $r = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1315 wfProfileOut( $fname );
1316 return $r;
1317 }
1318
1319 # Pass a title object, not a title string
1320 function makeBrokenLinkObj( &$nt, $text = "", $query = "", $trail = "" )
1321 {
1322 global $wgOut, $wgUser;
1323
1324 $fname = "Skin::makeBrokenLinkObj";
1325 wfProfileIn( $fname );
1326
1327 $link = $nt->getPrefixedURL();
1328
1329 if ( "" == $query ) { $q = "action=edit"; }
1330 else { $q = "action=edit&{$query}"; }
1331 $u = wfLocalUrlE( $link, $q );
1332
1333 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1334 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1335
1336 $inside = "";
1337 if ( "" != $trail ) {
1338 if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
1339 $inside = $m[1];
1340 $trail = $m[2];
1341 }
1342 }
1343 if ( $wgOut->isPrintable() ||
1344 ( 1 == $wgUser->getOption( "highlightbroken" ) ) ) {
1345 $s = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1346 } else {
1347 $s = "{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1348 }
1349
1350 wfProfileOut( $fname );
1351 return $s;
1352 }
1353
1354 # Pass a title object, not a title string
1355 function makeStubLinkObj( &$nt, $text = "", $query = "", $trail = "" )
1356 {
1357 global $wgOut, $wgUser;
1358
1359 $link = $nt->getPrefixedURL();
1360
1361 $u = wfLocalUrlE( $link, $query );
1362
1363 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1364 $style = $this->getInternalLinkAttributesObj( $nt, $text, "stub" );
1365
1366 $inside = "";
1367 if ( "" != $trail ) {
1368 if ( preg_match( wfMsg("linktrail"), $trail, $m ) ) {
1369 $inside = $m[1];
1370 $trail = $m[2];
1371 }
1372 }
1373 if ( $wgOut->isPrintable() ||
1374 ( 1 == $wgUser->getOption( "highlightbroken" ) ) ) {
1375 $s = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1376 } else {
1377 $s = "{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1378 }
1379 return $s;
1380 }
1381
1382 function fnamePart( $url )
1383 {
1384 $basename = strrchr( $url, "/" );
1385 if ( false === $basename ) { $basename = $url; }
1386 else { $basename = substr( $basename, 1 ); }
1387 return wfEscapeHTML( $basename );
1388 }
1389
1390 function makeImage( $url, $alt = "" )
1391 {
1392 global $wgOut;
1393
1394 if ( "" == $alt ) { $alt = $this->fnamePart( $url ); }
1395 $s = "<img src=\"{$url}\" alt=\"{$alt}\">";
1396 return $s;
1397 }
1398
1399 function makeImageLink( $name, $url, $alt = "" ) {
1400 $nt = Title::makeTitle( Namespace::getImage(), $name );
1401 return $this->makeImageLinkObj( $nt, $alt );
1402 }
1403
1404 function makeImageLinkObj( $nt, $alt = "" ) {
1405 $link = $nt->getPrefixedURL();
1406 $name = $nt->getDBKey();
1407 $url = wfImageUrl( $name );
1408 if ( empty( $alt ) ) {
1409 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1410 }
1411 $alt = htmlspecialchars( $alt );
1412
1413 $u = wfLocalUrlE( $link );
1414 $s = "<a href=\"{$u}\" class='image' title=\"{$alt}\">" .
1415 "<img border=\"0\" src=\"{$url}\" alt=\"{$alt}\"></a>";
1416 return $s;
1417 }
1418
1419 function makeMediaLink( $name, $url, $alt = "" ) {
1420 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1421 return $this->makeMediaLinkObj( $nt, $alt );
1422 }
1423
1424 function makeMediaLinkObj( $nt, $alt = "" )
1425 {
1426 $name = $nt->getDBKey();
1427 $url = wfImageUrl( $name );
1428 if ( empty( $alt ) ) {
1429 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1430 }
1431
1432 $u = htmlspecialchars( $url );
1433 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1434 return $s;
1435 }
1436
1437 function specialLink( $name, $key = "" )
1438 {
1439 global $wgLang;
1440
1441 if ( "" == $key ) { $key = strtolower( $name ); }
1442 $pn = $wgLang->ucfirst( $name );
1443 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1444 wfMsg( $key ) );
1445 }
1446
1447 # Called by history lists and recent changes
1448 #
1449
1450 function beginRecentChangesList()
1451 {
1452 $rc_cache = array() ;
1453 $rccc = 0 ;
1454 $this->lastdate = "";
1455 return "";
1456 }
1457
1458 function beginImageHistoryList()
1459 {
1460 $s = "\n<h2>" . wfMsg( "imghistory" ) . "</h2>\n" .
1461 "<p>" . wfMsg( "imghistlegend" ) . "\n<ul>";
1462 return $s;
1463 }
1464
1465 function endRecentChangesList()
1466 {
1467 $s = $this->recentChangesBlock() ;
1468 $s .= "</ul>\n";
1469 return $s;
1470 }
1471
1472 function endImageHistoryList()
1473 {
1474 $s = "</ul>\n";
1475 return $s;
1476 }
1477
1478 function recentChangesBlockLine ( $y ) {
1479 global $wgUploadPath ;
1480
1481 $M = wfMsg( "minoreditletter" );
1482 $N = wfMsg( "newpageletter" );
1483 $r = "" ;
1484 $r .= "<img src='{$wgUploadPath}/Arr_.png' width=12 height=12 border=0>" ;
1485 $r .= "<tt>" ;
1486 if ( $y->isnew ) $r .= $N ;
1487 else $r .= "&nbsp;" ;
1488 if ( $y->isminor ) $r .= $M ;
1489 else $r .= "&nbsp;" ;
1490 $r .= " ".$y->timestamp." " ;
1491 $r .= "</tt>" ;
1492 $link = $y->link ;
1493 if ( $y->watched ) $link = "<strong>{$link}</strong>" ;
1494 $r .= $link ;
1495
1496 $r .= " (" ;
1497 $r .= $y->curlink ;
1498 $r .= "; " ;
1499 $r .= $this->makeKnownLink( $y->secureName, wfMsg( "hist" ), "action=history" );
1500
1501 $r .= ") . . ".$y->userlink ;
1502 $r .= $y->usertalklink ;
1503 if ( $y->usercomment != "" )
1504 $r .= " <em>(".wfEscapeHTML($y->usercomment).")</em>" ;
1505 $r .= "<br>\n" ;
1506 return $r ;
1507 }
1508
1509 function recentChangesBlockGroup ( $y ) {
1510 global $wgUploadPath ;
1511
1512 $r = "" ;
1513 $M = wfMsg( "minoreditletter" );
1514 $N = wfMsg( "newpageletter" );
1515 $isnew = false ;
1516 $userlinks = array () ;
1517 foreach ( $y AS $x ) {
1518 $oldid = $x->diffid ;
1519 if ( $x->isnew ) $isnew = true ;
1520 $u = $x->userlink ;
1521 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
1522 $userlinks[$u]++ ;
1523 }
1524
1525 krsort ( $userlinks ) ;
1526 asort ( $userlinks ) ;
1527 $users = array () ;
1528 $u = array_keys ( $userlinks ) ;
1529 foreach ( $u as $x ) {
1530 $z = $x ;
1531 if ( $userlinks[$x] > 1 ) $z .= " ({$userlinks[$x]}&times;)" ;
1532 array_push ( $users , $z ) ;
1533 }
1534 $users = " <font size='-1'>[".implode("; ",$users)."]</font>" ;
1535
1536 $e = $y ;
1537 $e = array_shift ( $e ) ;
1538
1539 # Arrow
1540 $rci = "RCI{$this->rccc}" ;
1541 $rcl = "RCL{$this->rccc}" ;
1542 $rcm = "RCM{$this->rccc}" ;
1543 $tl = "<a href='javascript:toggleVisibility(\"{$rci}\",\"{$rcm}\",\"{$rcl}\")'>" ;
1544 $tl .= "<span id='{$rcm}'><img src='{$wgUploadPath}/Arr_r.png' width=12 height=12 border=0></span>" ;
1545 $tl .= "<span id='{$rcl}' style='display:none'><img src='{$wgUploadPath}/Arr_d.png' width=12 height=12 border=0></span>" ;
1546 $tl .= "</a>" ;
1547 $r .= $tl ;
1548
1549 # Main line
1550 $r .= "<tt>" ;
1551 if ( $isnew ) $r .= $N ;
1552 else $r .= "&nbsp;" ;
1553 $r .= "&nbsp;" ; # Minor
1554 $r .= " ".$e->timestamp." " ;
1555 $r .= "</tt>" ;
1556
1557 $link = $e->link ;
1558 if ( $e->watched ) $link = "<strong>{$link}</strong>" ;
1559 $r .= $link ;
1560
1561 if ( !$e->islog ) {
1562 $r .= " (".count($y)." " ;
1563 if ( $isnew ) $r .= wfMsg("changes");
1564 else $r .= $this->makeKnownLink( $e->secureName , wfMsg("changes") , "diff=0&oldid=".$oldid ) ;
1565 $r .= "; " ;
1566 $r .= $this->makeKnownLink( $e->secureName, wfMsg( "history" ), "action=history" );
1567 $r .= ")" ;
1568 }
1569
1570 $r .= $users ;
1571 $r .= "<br>\n" ;
1572
1573 # Sub-entries
1574 $r .= "<div id='{$rci}' style='display:none'>" ;
1575 foreach ( $y AS $x )
1576 {
1577 $r .= "<img src='{$wgUploadPath}/Arr_.png' width=12 height=12 border=0>";
1578 $r .= "<tt>&nbsp; &nbsp; &nbsp; &nbsp;" ;
1579 if ( $x->isnew ) $r .= $N ;
1580 else $r .= "&nbsp;" ;
1581 if ( $x->isminor ) $r .= $M ;
1582 else $r .= "&nbsp;" ;
1583 $r .= "</tt>" ;
1584
1585 $o = "" ;
1586 if ( $x->oldid != 0 ) $o = "oldid=".$x->oldid ;
1587 if ( $x->islog ) $link = $x->timestamp ;
1588 else $link = $this->makeKnownLink( $x->secureName, $x->timestamp , $o ) ;
1589 $link = "<tt>{$link}</tt>" ;
1590
1591
1592 $r .= $link ;
1593 $r .= " (" ;
1594 $r .= $x->curlink ;
1595 $r .= "; " ;
1596 $r .= $x->lastlink ;
1597 $r .= ") . . ".$x->userlink ;
1598 $r .= $x->usertalklink ;
1599 if ( $x->usercomment != "" )
1600 $r .= " <em>(".wfEscapeHTML($x->usercomment).")</em>" ;
1601 $r .= "<br>\n" ;
1602 }
1603 $r .= "</div>\n" ;
1604
1605 $this->rccc++ ;
1606 return $r ;
1607 }
1608
1609 function recentChangesBlock ()
1610 {
1611 global $wgUploadPath ;
1612 if ( count ( $this->rc_cache ) == 0 ) return "" ;
1613 $k = array_keys ( $this->rc_cache ) ;
1614 foreach ( $k AS $x )
1615 {
1616 $y = $this->rc_cache[$x] ;
1617 if ( count ( $y ) < 2 ) {
1618 $r .= $this->recentChangesBlockLine ( array_shift ( $y ) ) ;
1619 } else {
1620 $r .= $this->recentChangesBlockGroup ( $y ) ;
1621 }
1622 }
1623
1624 return "<div align=left>{$r}</div>" ;
1625 }
1626
1627 function recentChangesLine( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
1628 {
1629 global $wgUser ;
1630 $usenew = $wgUser->getOption( "usenewrc" );
1631 if ( $usenew )
1632 $r = $this->recentChangesLineNew ( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched , $oldid , $diffid ) ;
1633 else
1634 $r = $this->recentChangesLineOld ( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched , $oldid , $diffid ) ;
1635 return $r ;
1636 }
1637
1638 function recentChangesLineOld( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0, $diffid = 0 )
1639 {
1640 global $wgTitle, $wgLang, $wgUser;
1641
1642 $d = $wgLang->date( $ts, true);
1643 $s = "";
1644 if ( $d != $this->lastdate ) {
1645 if ( "" != $this->lastdate ) { $s .= "</ul>\n"; }
1646 $s .= "<h4>{$d}</h4>\n<ul>";
1647 $this->lastdate = $d;
1648 }
1649 $h = $wgLang->time( $ts, true );
1650 $t = Title::makeName( $ns, $ttl );
1651 $clink = $this->makeKnownLink( $t , "" );
1652 $nt = Title::newFromText( $t );
1653
1654 if ( $watched ) {
1655 $clink = "<strong>{$clink}</strong>";
1656 }
1657 $hlink = $this->makeKnownLink( $t, wfMsg( "hist" ), "action=history" );
1658 if ( $isnew || $nt->isLog() ) {
1659 $dlink = wfMsg( "diff" );
1660 } else {
1661 $dlink = $this->makeKnownLink( $t, wfMsg( "diff" ),
1662 "diff={$oldid}&oldid={$diffid}" ); # Finagle's law
1663 }
1664 if ( 0 == $u ) {
1665 $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1666 $ut, "target=" . $ut );
1667 } else {
1668 $ul = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) . ":{$ut}", $ut );
1669 }
1670
1671 $talkname=$wgLang->getNsText(Namespace::getTalk(0)); # use the shorter name
1672 global $wgDisableAnonTalk;
1673 if( 0 == $u && $wgDisableAnonTalk ) {
1674 $utl = "";
1675 } else {
1676 $utns=$wgLang->getNsText(Namespace::getTalk(Namespace::getUser()));
1677 $utl= $this->makeLink($utns . ":{$ut}", $talkname );
1678 }
1679 $cr = wfMsg( "currentrev" );
1680
1681 $s .= "<li> ({$dlink}) ({$hlink}) . .";
1682 $M = wfMsg( "minoreditletter" );
1683 $N = wfMsg( "newpageletter" );
1684 if ( $isminor ) { $s .= " <strong>{$M}</strong>"; }
1685 if ( $isnew ) { $s .= "<strong>{$N}</strong>"; }
1686 $s .= " {$clink}; {$h} . . {$ul}";
1687
1688 $blink="";
1689 if ( ( 0 == $u ) && $wgUser->isSysop() ) {
1690 $blink = $this->makeKnownLink( $wgLang->specialPage(
1691 "Blockip" ), wfMsg( "blocklink" ), "ip={$ut}" );
1692
1693 }
1694 if($blink) {
1695 if($utl) $utl .= " | ";
1696 $utl .= $blink;
1697 }
1698 if($utl) $s.=" ({$utl})";
1699
1700 if ( "" != $c && "*" != $c ) {
1701 $s .= " <em>(" . wfEscapeHTML( $c ) . ")</em>";
1702 }
1703 $s .= "</li>\n";
1704
1705 return $s;
1706 }
1707
1708 function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
1709 {
1710 global $wgTitle, $wgLang, $wgUser;
1711
1712 $rc = new RecentChangesClass ;
1713
1714 $d = $wgLang->date( $ts, true);
1715 $s = "";
1716 $ret = "" ;
1717 if ( $d != $this->lastdate ) {
1718 $ret = $this->recentChangesBlock () ;
1719 $this->rc_cache = array() ;
1720 $ret .= "<h4>{$d}</h4>\n";
1721 $this->lastdate = $d;
1722 }
1723 $h = $wgLang->time( $ts, true );
1724 $t = Title::makeName( $ns, $ttl );
1725 $clink = $this->makeKnownLink( $t, "" ) ;
1726 if ( $oldid == 0 ) $c2link = $clink ;
1727 else $c2link = $this->makeKnownLink( $t, "" , "oldid={$oldid}" );
1728 $nt = Title::newFromText( $t );
1729
1730 $rc->timestamp = $h ;
1731 $rc->oldid = $oldid ;
1732 $rc->diffid = $diffid ;
1733 $rc->watched = $watched ;
1734 $rc->isnew = $isnew ;
1735 $rc->isminor = $isminor ;
1736 $rc->secureName = $t ;
1737 $rc->displayName = $nt ;
1738 $rc->link = $clink ;
1739 $rc->usercomment = $c ;
1740 $rc->islog = $nt->isLog() ;
1741
1742 if ( ( $isnew && $oldid == 0 ) || $nt->isLog() ) {
1743 $dlink = wfMsg( "cur" );
1744 } else {
1745 $dlink = $this->makeKnownLink( $t, wfMsg( "cur" ),
1746 "diff=0&oldid={$oldid}" );
1747 }
1748
1749 if ( $diffid == 0 || $nt->isLog() ) {
1750 $plink = wfMsg( "last" );
1751 } else {
1752 $plink = $this->makeKnownLink( $t, wfMsg( "last" ),
1753 "diff={$oldid}&oldid={$diffid}" );
1754 }
1755
1756 if ( 0 == $u ) {
1757 $ul = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1758 $ut, "target=" . $ut );
1759 } else { $ul = $this->makeLink( $wgLang->getNsText(
1760 Namespace::getUser() ) . ":{$ut}", $ut ); }
1761
1762 $rc->userlink = $ul ;
1763 $rc->lastlink = $plink ;
1764 $rc->curlink = $dlink ;
1765
1766 $utns=$wgLang->getNsText(Namespace::getTalk(Namespace::getUser()));
1767 $talkname=$wgLang->getNsText(Namespace::getTalk(0)); # use the shorter name
1768 $utl= $this->makeLink($utns . ":{$ut}", $talkname );
1769
1770 global $wgDisableAnonTalk;
1771 if ( ( 0 == $u ) && $wgUser->isSysop() ) {
1772 $blink = $this->makeKnownLink( $wgLang->specialPage(
1773 "Blockip" ), wfMsg( "blocklink" ), "ip={$ut}" );
1774 if( $wgDisableAnonTalk )
1775 $rc->usertalklink = " ({$blink})";
1776 else
1777 $rc->usertalklink = " ({$utl} | {$blink})";
1778 } else {
1779 if( $wgDisableAnonTalk && ($u == 0) )
1780 $rc->usertalklink = "";
1781 else
1782 $rc->usertalklink = " ({$utl})";
1783 }
1784
1785 if ( !isset ( $this->rc_cache[$t] ) ) $this->rc_cache[$t] = array() ;
1786 array_push ( $this->rc_cache[$t] , $rc ) ;
1787 return $ret;
1788 }
1789
1790
1791 function imageHistoryLine( $iscur, $ts, $img, $u, $ut, $size, $c )
1792 {
1793 global $wgUser, $wgLang, $wgTitle;
1794
1795 $dt = $wgLang->timeanddate( $ts, true );
1796 $del = wfMsg( "deleteimg" );
1797 $cur = wfMsg( "cur" );
1798
1799 if ( $iscur ) {
1800 $url = wfImageUrl( $img );
1801 $rlink = $cur;
1802 if ( $wgUser->isSysop() ) {
1803 $link = wfLocalUrlE( $wgTitle->getPrefixedText(), "image=" . $wgTitle->getURL() .
1804 "&action=delete" );
1805 $style = $this->getInternalLinkAttributes( $link, $del );
1806
1807 $dlink = "<a href=\"{$link}\"{$style}>{$del}</a>";
1808 } else {
1809 $dlink = $del;
1810 }
1811 } else {
1812 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
1813 if( $wgUser->getID() != 0 ) {
1814 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1815 wfMsg( "revertimg" ), "action=revert&oldimage=" .
1816 urlencode( $img ) );
1817 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1818 $del, "action=delete&oldimage=" . urlencode( $img ) );
1819 } else {
1820 # Having live active links for non-logged in users
1821 # means that bots and spiders crawling our site can
1822 # inadvertently change content. Baaaad idea.
1823 $rlink = wfMsg( "revertimg" );
1824 $dlink = $del;
1825 }
1826 }
1827 if ( 0 == $u ) { $ul = $ut; }
1828 else { $ul = $this->makeLink( $wgLang->getNsText(
1829 Namespace::getUser() ) . ":{$ut}", $ut ); }
1830
1831 $nb = wfMsg( "nbytes", $size );
1832 $style = $this->getInternalLinkAttributes( $url, $dt );
1833
1834 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$dt}</a>"
1835 . " . . {$ul} ({$nb})";
1836
1837 if ( "" != $c && "*" != $c ) {
1838 $s .= " <em>(" . wfEscapeHTML( $c ) . ")</em>";
1839 }
1840 $s .= "</li>\n";
1841 return $s;
1842 }
1843
1844 function tocIndent($level) {
1845
1846 while($level-->0) $rv.="<div style=\"margin-left:2em;\">\n";
1847 return $rv;
1848
1849 }
1850
1851 function tocUnindent($level) {
1852 while($level-->0) $rv.="</div>\n";
1853 return $rv;
1854 }
1855
1856 // parameter level defines if we are on an indentation level
1857 function tocLine($anchor,$tocline,$level) {
1858
1859 if($level) {
1860
1861 return "<A CLASS=\"internal\" HREF=\"#".$anchor."\">".$tocline."</A><BR>\n";
1862 } else {
1863
1864 return "<div style=\"margin-bottom:0px;\">\n".
1865 "<A CLASS=\"internal\" HREF=\"#".$anchor."\">".$tocline."</A><BR>\n".
1866 "</div>\n";
1867 }
1868
1869 }
1870
1871 function tocTable($toc) {
1872 // note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
1873 global $printable;
1874
1875 if (!$printable) {
1876 $hideline = " <script type='text/javascript'>showTocToggle(\"" . wfMsg("showtoc") . "\",\"" . wfMsg("hidetoc") . "\")</script>";
1877 }
1878 return
1879 "<p><table border=\"0\" id=\"toc\"><tr><td align=\"center\">\n".
1880 "<b>".wfMsg("toc")."</b>" .
1881 $hideline .
1882 "</td></tr><tr id='tocinside'><td align=\"left\">\n".
1883 $toc."</td></tr></table><P>\n";
1884 }
1885
1886 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
1887 function editSectionScript($section,$head) {
1888
1889 global $wgTitle,$wgUser,$oldid;
1890 if($oldid) return $head;
1891 $url = wfLocalUrlE(urlencode($wgTitle->getPrefixedText()),"action=edit&section=$section");
1892 return "<span onContextMenu='document.location=\"".$url."\";return false;'>{$head}</span>";
1893 }
1894
1895 function editSectionLink($section) {
1896
1897 global $printable;
1898 global $wgTitle,$wgUser,$oldid;
1899 if($oldid) return "";
1900 if ($printable) return "";
1901 $editurl="&section={$section}";
1902 $url=$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("editsection"),"action=edit".$editurl);
1903 return "<div style=\"float:right;margin-left:5px;\"><small>[".$url."]</small></div>";
1904
1905 }
1906 }
1907
1908 include_once( "SkinStandard.php" );
1909 include_once( "SkinNostalgia.php" );
1910 include_once( "SkinCologneBlue.php" );
1911
1912 #include_once( "SkinSmarty.php" );
1913
1914 ?>