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