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