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