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