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