div instead of p, included things might contain blocklevel elements themselves
[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( $wgUsePHPTal ) {
17 #$wgValidSkinNames[] = "PHPTal";
18 #$wgValidSkinNames['davinci'] = "DaVinci";
19 #$wgValidSkinNames['mono'] = "Mono";
20 $wgValidSkinNames['monobook'] = "MonoBook";
21 #$wgValidSkinNames['monobookminimal'] = "MonoBookMinimal";
22 }
23
24 include_once( "RecentChange.php" );
25
26 # For some odd PHP bug, this function can't be part of a class
27 function getCategories ()
28 {
29 global $wgOut , $wgTitle , $wgUseCategoryMagic , $wgUser , $wgParser ;
30 if ( !isset ( $wgUseCategoryMagic ) || !$wgUseCategoryMagic ) return "" ;
31 if ( count ( $wgOut->mCategoryLinks ) == 0 ) return "" ;
32 if ( !$wgOut->isArticle() ) return "" ;
33 $sk = $wgUser->getSkin() ;
34 $s = "" ;
35 $s .= $sk->makeKnownLink ( "Special:Categories" , "Categories" , "article=".$wgTitle->getDBkey() ) ;
36 $t = implode ( " | " , $wgOut->mCategoryLinks ) ;
37 if ( $t != "" ) $s .= ": " ;
38 $s .= $t ;
39 return "<p class='catlinks'>$s</p>";
40 }
41
42 class RCCacheEntry extends RecentChange
43 {
44 var $secureName, $link;
45 var $curlink , $lastlink , $usertalklink , $versionlink ;
46 var $userlink, $timestamp, $watched;
47
48 function newFromParent( $rc )
49 {
50 $rc2 = new RCCacheEntry;
51 $rc2->mAttribs = $rc->mAttribs;
52 $rc2->mExtra = $rc->mExtra;
53 return $rc2;
54 }
55 } ;
56
57 class Skin {
58
59 /* private */ var $lastdate, $lastline;
60 var $linktrail ; # linktrail regexp
61 var $rc_cache ; # Cache for Enhanced Recent Changes
62 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
63 var $rcMoveIndex;
64
65 function Skin()
66 {
67 $this->linktrail = wfMsg("linktrail");
68 }
69
70 function getSkinNames()
71 {
72 global $wgValidSkinNames;
73 return $wgValidSkinNames;
74 }
75
76 function getStylesheet()
77 {
78 return "wikistandard.css";
79 }
80
81 function qbSetting()
82 {
83 global $wgOut, $wgUser;
84
85 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
86 $q = $wgUser->getOption( "quickbar" );
87 if ( "" == $q ) { $q = 0; }
88 return $q;
89 }
90
91 function initPage( &$out )
92 {
93 $fname = "Skin::initPage";
94 wfProfileIn( $fname );
95
96 $out->addLink( array( "rel" => "shortcut icon", "href" => "/favicon.ico" ) );
97
98 $this->addMetadataLinks($out);
99
100 wfProfileOut( $fname );
101 }
102
103 function addMetadataLinks( &$out ) {
104 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
105 global $wgRightsPage, $wgRightsUrl;
106
107 if( $out->isArticleRelated() ) {
108 # note: buggy CC software only reads first "meta" link
109 if( $wgEnableCreativeCommonsRdf ) {
110 $out->addMetadataLink( array(
111 'title' => 'Creative Commons',
112 'type' => 'application/rdf+xml',
113 'href' => $wgTitle->getLocalURL( "action=creativecommons") ) );
114 }
115 if( $wgEnableDublinCoreRdf ) {
116 $out->addMetadataLink( array(
117 'title' => 'Dublin Core',
118 'type' => 'application/rdf+xml',
119 'href' => $wgTitle->getLocalURL( "action=dublincore" ) ) );
120 }
121 }
122 $copyright = "";
123 if( $wgRightsPage ) {
124 $copy = Title::newFromText( $wgRightsPage );
125 if( $copy ) {
126 $copyright = $copy->getLocalURL();
127 }
128 }
129 if( !$copyright && $wgRightsUrl ) {
130 $copyright = $wgRightsUrl;
131 }
132 if( $copyright ) {
133 $out->addLink( array(
134 "rel" => "copyright",
135 "href" => $copyright ) );
136 }
137 }
138
139 function outputPage( &$out ) {
140 global $wgDebugComments;
141
142 wfProfileIn( "Skin::outputPage" );
143 $this->initPage( $out );
144 $out->out( $out->headElement() );
145
146 $out->out( "\n<body" );
147 $ops = $this->getBodyOptions();
148 foreach ( $ops as $name => $val ) {
149 $out->out( " $name='$val'" );
150 }
151 $out->out( ">\n" );
152 if ( $wgDebugComments ) {
153 $out->out( "<!-- Wiki debugging output:\n" .
154 $out->mDebugtext . "-->\n" );
155 }
156 $out->out( $this->beforeContent() );
157
158 $out->out( $out->mBodytext . "\n" );
159
160 $out->out( $this->afterContent() );
161
162 wfProfileClose();
163 $out->out( $out->reportTime() );
164
165 $out->out( "\n</body></html>" );
166 }
167
168 function getHeadScripts() {
169 global $wgStyleSheetPath;
170 $r = "<script type=\"text/javascript\" src=\"{$wgStyleSheetPath}/wikibits.js\"></script>\n";
171 return $r;
172 }
173
174 function getUserStyles()
175 {
176 global $wgOut, $wgStyleSheetPath;
177 $sheet = $this->getStylesheet();
178 $s = "<style type='text/css'>\n";
179 $s .= "/*/*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
180 $s .= "@import url(\"$wgStyleSheetPath/$sheet\");\n";
181 $s .= $this->doGetUserStyles();
182 $s .= "/* */\n";
183 $s .= "</style>\n";
184 return $s;
185 }
186
187 function doGetUserStyles()
188 {
189 global $wgUser;
190
191 $s = "";
192 if ( 1 == $wgUser->getOption( "underline" ) ) {
193 # Don't override browser settings
194 } else {
195 # CHECK MERGE @@@
196 # Force no underline
197 $s .= "a { " .
198 "text-decoration: none; }\n";
199 }
200 if ( 1 == $wgUser->getOption( "highlightbroken" ) ) {
201 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
202 }
203 if ( 1 == $wgUser->getOption( "justify" ) ) {
204 $s .= "#article { text-align: justify; }\n";
205 }
206 return $s;
207 }
208
209 function getBodyOptions()
210 {
211 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
212
213 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
214
215 if ( 0 != $wgTitle->getNamespace() ) {
216 $a = array( "bgcolor" => "#ffffec" );
217 }
218 else $a = array( "bgcolor" => "#FFFFFF" );
219 if($wgOut->isArticle() && $wgUser->getOption("editondblclick") &&
220 (!$wgTitle->isProtected() || $wgUser->isSysop()) ) {
221 $t = wfMsg( "editthispage" );
222 $oid = $red = "";
223 if ( $redirect ) {
224 $red = "&redirect={$redirect}";
225 }
226 if ( !empty($oldid) && ! isset( $diff ) ) {
227 $oid = "&oldid={$oldid}";
228 }
229 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
230 $s = "document.location = \"" .$s ."\";";
231 $a += array ("ondblclick" => $s);
232
233 }
234 $a['onload'] = $wgOut->getOnloadHandler();
235 return $a;
236 }
237
238 function getExternalLinkAttributes( $link, $text )
239 {
240 global $wgUser, $wgOut, $wgLang;
241
242 $link = urldecode( $link );
243 $link = $wgLang->checkTitleEncoding( $link );
244 $link = str_replace( "_", " ", $link );
245 $link = wfEscapeHTML( $link );
246
247 $r = " class='external'";
248
249 if ( 1 == $wgUser->getOption( "hover" ) ) {
250 $r .= " title=\"{$link}\"";
251 }
252 return $r;
253 }
254
255 function getInternalLinkAttributes( $link, $text, $broken = false )
256 {
257 global $wgUser, $wgOut;
258
259 $link = urldecode( $link );
260 $link = str_replace( "_", " ", $link );
261 $link = wfEscapeHTML( $link );
262
263 if ( $broken == "stub" ) {
264 $r = " class='stub'";
265 } else if ( $broken == "yes" ) {
266 $r = " class='new'";
267 } else {
268 $r = "";
269 }
270
271 if ( 1 == $wgUser->getOption( "hover" ) ) {
272 $r .= " title=\"{$link}\"";
273 }
274 return $r;
275 }
276
277 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
278 {
279 global $wgUser, $wgOut;
280
281 if ( $broken == "stub" ) {
282 $r = " class='stub'";
283 } else if ( $broken == "yes" ) {
284 $r = " class='new'";
285 } else {
286 $r = "";
287 }
288
289 if ( 1 == $wgUser->getOption( "hover" ) ) {
290 $r .= ' title ="' . $nt->getEscapedText() . '"';
291 }
292 return $r;
293 }
294
295 function getLogo()
296 {
297 global $wgLogo;
298 return $wgLogo;
299 }
300
301 # This will be called immediately after the <body> tag. Split into
302 # two functions to make it easier to subclass.
303 #
304 function beforeContent()
305 {
306 global $wgUser, $wgOut, $wgSiteNotice;
307
308 if( $wgSiteNotice ) {
309 $note = "\n<div id='notice' style='font-weight: bold; color: red; text-align: center'>$wgSiteNotice</div>\n";
310 } else {
311 $note = "";
312 }
313 return $this->doBeforeContent() . $note;
314 }
315
316 function doBeforeContent()
317 {
318 global $wgUser, $wgOut, $wgTitle, $wgLang;
319 $fname = "Skin::doBeforeContent";
320 wfProfileIn( $fname );
321
322 $s = "";
323 $qb = $this->qbSetting();
324
325 if( $langlinks = $this->otherLanguages() ) {
326 $rows = 2;
327 $borderhack = "";
328 } else {
329 $rows = 1;
330 $langlinks = false;
331 $borderhack = "class='top'";
332 }
333
334 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
335 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
336
337 $shove = ($qb != 0);
338 $left = ($qb == 1 || $qb == 3);
339 if($wgLang->isRTL()) $left = !$left;
340
341 if ( !$shove ) {
342 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
343 $this->logoText() . "</td>";
344 } elseif( $left ) {
345 $s .= $this->getQuickbarCompensator( $rows );
346 }
347 $l = $wgLang->isRTL() ? "right" : "left";
348 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
349
350 $s .= $this->topLinks() ;
351 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
352
353 $r = $wgLang->isRTL() ? "left" : "right";
354 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
355 $s .= $this->nameAndLogin();
356 $s .= "\n<br />" . $this->searchForm() . "</td>";
357
358 if ( $langlinks ) {
359 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
360 }
361
362 if ( $shove && !$left ) { # Right
363 $s .= $this->getQuickbarCompensator( $rows );
364 }
365 $s .= "</tr>\n</table>\n</div>\n";
366 $s .= "\n<div id='article'>\n";
367
368 $s .= $this->pageTitle();
369 $s .= $this->pageSubtitle() ;
370 $s .= getCategories(); // For some odd reason, zhis can't be a function of the object
371 wfProfileOut( $fname );
372 return $s;
373 }
374
375 function getQuickbarCompensator( $rows = 1 )
376 {
377 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
378 }
379
380 # This gets called immediately before the </body> tag.
381 #
382 function afterContent()
383 {
384 global $wgUser, $wgOut, $wgServer;
385 global $wgTitle, $wgLang;
386
387 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
388 return $printfooter . $this->doAfterContent();
389 }
390
391 function printFooter() {
392 global $wgTitle;
393 $url = htmlspecialchars( $wgTitle->getFullURL() );
394 return "<p>" . wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" ) .
395 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
396 }
397
398 function doAfterContent()
399 {
400 global $wgUser, $wgOut, $wgLang;
401 $fname = "Skin::doAfterContent";
402 wfProfileIn( $fname );
403 wfProfileIn( "$fname-1" );
404
405 $s = "\n</div><br clear='all' />\n";
406 $s .= "\n<div id='footer'>";
407 $s .= "<table border='0' cellspacing='0'><tr>";
408
409 wfProfileOut( "$fname-1" );
410 wfProfileIn( "$fname-2" );
411
412 $qb = $this->qbSetting();
413 $shove = ($qb != 0);
414 $left = ($qb == 1 || $qb == 3);
415 if($wgLang->isRTL()) $left = !$left;
416
417 if ( $shove && $left ) { # Left
418 $s .= $this->getQuickbarCompensator();
419 }
420 wfProfileOut( "$fname-2" );
421 wfProfileIn( "$fname-3" );
422 $l = $wgLang->isRTL() ? "right" : "left";
423 $s .= "<td class='bottom' align='$l' valign='top'>";
424
425 $s .= $this->bottomLinks();
426 $s .= "\n<br />" . $this->mainPageLink()
427 . " | " . $this->aboutLink()
428 . " | " . $this->specialLink( "recentchanges" )
429 . " | " . $this->searchForm()
430 . "<br /><span id='pagestats'>" . $this->pageStats() . "</span>";
431
432 $s .= "</td>";
433 if ( $shove && !$left ) { # Right
434 $s .= $this->getQuickbarCompensator();
435 }
436 $s .= "</tr></table>\n</div>\n</div>\n";
437
438 wfProfileOut( "$fname-3" );
439 wfProfileIn( "$fname-4" );
440 if ( 0 != $qb ) { $s .= $this->quickBar(); }
441 wfProfileOut( "$fname-4" );
442 wfProfileOut( $fname );
443 return $s;
444 }
445
446 function pageTitleLinks()
447 {
448 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
449
450 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
451 $action = $wgRequest->getText( 'action' );
452
453 $s = $this->printableLink();
454 if ( wfMsg ( "disclaimers" ) != "" ) $s .= " | " . $this->makeKnownLink( wfMsg( "disclaimerpage" ), wfMsg( "disclaimers" ) ) ;
455
456 if ( $wgOut->isArticleRelated() ) {
457 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
458 $name = $wgTitle->getDBkey();
459 $link = wfEscapeHTML( wfImageUrl( $name ) );
460 $style = $this->getInternalLinkAttributes( $link, $name );
461 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
462 }
463 # This will show the "Approve" link if $wgUseApproval=true;
464 if ( isset ( $wgUseApproval ) && $wgUseApproval )
465 {
466 $t = $wgTitle->getDBkey();
467 $name = "Approve this article" ;
468 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
469 #wfEscapeHTML( wfImageUrl( $name ) );
470 $style = $this->getExternalLinkAttributes( $link, $name );
471 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
472 }
473 }
474 if ( "history" == $action || isset( $diff ) || isset( $oldid ) ) {
475 $s .= " | " . $this->makeKnownLink( $wgTitle->getPrefixedText(),
476 wfMsg( "currentrev" ) );
477 }
478
479 if ( $wgUser->getNewtalk() ) {
480 # do not show "You have new messages" text when we are viewing our
481 # own talk page
482
483 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
484 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
485 $n =$wgUser->getName();
486 $tl = $this->makeKnownLink( $wgLang->getNsText(
487 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
488 wfMsg("newmessageslink") );
489 $s.=" | <strong>". wfMsg( "newmessages", $tl ) . "</strong>";
490 }
491 }
492 if( $wgUser->isSysop() &&
493 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
494 ($n = $wgTitle->isDeleted() ) ) {
495 $s .= " | " . wfMsg( "thisisdeleted",
496 $this->makeKnownLink(
497 $wgLang->SpecialPage( "Undelete/" . $wgTitle->getPrefixedDBkey() ),
498 wfMsg( "restorelink", $n ) ) );
499 }
500 return $s;
501 }
502
503 function printableLink()
504 {
505 global $wgOut, $wgFeedClasses, $wgRequest;
506
507 $baseurl = $_SERVER['REQUEST_URI'];
508 if( strpos( "?", $baseurl ) == false ) {
509 $baseurl .= "?";
510 } else {
511 $baseurl .= "&";
512 }
513 $baseurl = htmlspecialchars( $baseurl );
514 $printurl = $wgRequest->escapeAppendQuery( "printable=yes" );
515
516 $s = "<a href=\"$printurl\">" . wfMsg( "printableversion" ) . "</a>";
517 if( $wgOut->isSyndicated() ) {
518 foreach( $wgFeedClasses as $format => $class ) {
519 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
520 $s .= " | <a href=\"$feedurl\">{$format}</a>";
521 }
522 }
523 return $s;
524 }
525
526 function pageTitle()
527 {
528 global $wgOut, $wgTitle, $wgUser;
529
530 $s = "<h1 class='pagetitle'>" . $wgOut->getPageTitle() . "</h1>";
531 if($wgUser->getOption("editsectiononrightclick") && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
532 return $s;
533 }
534
535 function pageSubtitle()
536 {
537 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
538
539 $sub = $wgOut->getSubtitle();
540 if ( "" == $sub ) {
541 global $wgExtraSubtitle;
542 $sub = wfMsg( "fromwikipedia" ) . $wgExtraSubtitle;
543 }
544 if($wgOut->isArticle() && $wgNamespacesWithSubpages[$wgTitle->getNamespace()]) {
545 $ptext=$wgTitle->getPrefixedText();
546 if(preg_match("/\//",$ptext)) {
547 $sub.="</p><p class='subpages'>";
548 $links=explode("/",$ptext);
549 $c=0;
550 $growinglink="";
551 foreach($links as $link) {
552 $c++;
553 if ($c<count($links)) {
554 $growinglink .= $link;
555 $getlink = $this->makeLink( $growinglink, $link );
556 if(preg_match("/class='new'/i",$getlink)) { break; } # this is a hack, but it saves time
557 if ($c>1) {
558 $sub .= " | ";
559 } else {
560 $sub .="&lt; ";
561 }
562 $sub .= $getlink;
563 $growinglink.="/";
564 }
565
566 }
567 }
568 }
569 $s = "<p class='subtitle'>{$sub}</p>\n";
570 return $s;
571 }
572
573 function nameAndLogin()
574 {
575 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
576
577 $li = $wgLang->specialPage( "Userlogin" );
578 $lo = $wgLang->specialPage( "Userlogout" );
579
580 $s = "";
581 if ( 0 == $wgUser->getID() ) {
582 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get("session.name")] ) ) {
583 $n = $wgIP;
584
585 $tl = $this->makeKnownLink( $wgLang->getNsText(
586 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
587 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
588
589 $s .= $n . " (".$tl.")";
590 } else {
591 $s .= wfMsg("notloggedin");
592 }
593
594 $rt = $wgTitle->getPrefixedURL();
595 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
596 $q = "";
597 } else { $q = "returnto={$rt}"; }
598
599 $s .= "\n<br />" . $this->makeKnownLink( $li,
600 wfMsg( "login" ), $q );
601 } else {
602 $n = $wgUser->getName();
603 $rt = $wgTitle->getPrefixedURL();
604 $tl = $this->makeKnownLink( $wgLang->getNsText(
605 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
606 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
607
608 $tl = " ({$tl})";
609
610 $s .= $this->makeKnownLink( $wgLang->getNsText(
611 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
612 $this->makeKnownLink( $lo, wfMsg( "logout" ),
613 "returnto={$rt}" ) . " | " .
614 $this->specialLink( "preferences" );
615 }
616 $s .= " | " . $this->makeKnownLink( wfMsg( "helppage" ),
617 wfMsg( "help" ) );
618
619 return $s;
620 }
621
622 function searchForm()
623 {
624 global $wgRequest;
625
626 $search = $wgRequest->getText( 'search' );;
627
628 $s = "<form name='search' class='inline' method='post' action=\""
629 . wfLocalUrl( "" ) . "\">\n"
630 . "<input type='text' name=\"search\" size='19' value=\""
631 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
632 . "<input type='submit' name=\"go\" value=\"" . wfMsg ("go") . "\" />&nbsp;"
633 . "<input type='submit' name=\"fulltext\" value=\"" . wfMsg ("search") . "\" />\n</form>";
634
635 return $s;
636 }
637
638 function topLinks()
639 {
640 global $wgOut;
641 $sep = " |\n";
642
643 $s = $this->mainPageLink() . $sep
644 . $this->specialLink( "recentchanges" );
645
646 if ( $wgOut->isArticleRelated() ) {
647 $s .= $sep . $this->editThisPage()
648 . $sep . $this->historyLink();
649 }
650 # Many people don't like this dropdown box
651 #$s .= $sep . $this->specialPagesList();
652
653 return $s;
654 }
655
656 function bottomLinks()
657 {
658 global $wgOut, $wgUser, $wgTitle;
659 $sep = " |\n";
660
661 $s = "";
662 if ( $wgOut->isArticleRelated() ) {
663 $s .= "<strong>" . $this->editThisPage() . "</strong>";
664 if ( 0 != $wgUser->getID() ) {
665 $s .= $sep . $this->watchThisPage();
666 }
667 $s .= $sep . $this->talkLink()
668 . $sep . $this->historyLink()
669 . $sep . $this->whatLinksHere()
670 . $sep . $this->watchPageLinksLink();
671
672 if ( $wgTitle->getNamespace() == Namespace::getUser()
673 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
674
675 {
676 $id=User::idFromName($wgTitle->getText());
677 $ip=User::isIP($wgTitle->getText());
678
679 if($id || $ip) { # both anons and non-anons have contri list
680 $s .= $sep . $this->userContribsLink();
681 }
682 if ( 0 != $wgUser->getID() ) { # show only to signed in users
683 if($id) { # can only email non-anons
684 $s .= $sep . $this->emailUserLink();
685 }
686 }
687 }
688 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
689 $s .= "\n<br />" . $this->deleteThisPage() .
690 $sep . $this->protectThisPage() .
691 $sep . $this->moveThisPage();
692 }
693 $s .= "<br />\n" . $this->otherLanguages();
694 }
695 return $s;
696 }
697
698 function pageStats()
699 {
700 global $wgOut, $wgLang, $wgArticle, $wgRequest;
701 global $wgDisableCounters;
702
703 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
704 if ( ! $wgOut->isArticle() ) { return ""; }
705 if ( isset( $oldid ) || isset( $diff ) ) { return ""; }
706 if ( 0 == $wgArticle->getID() ) { return ""; }
707
708 $s = "";
709 if ( !$wgDisableCounters ) {
710 $count = $wgLang->formatNum( $wgArticle->getCount() );
711 if ( $count ) {
712 $s = wfMsg( "viewcount", $count );
713 }
714 }
715 $s .= $this->lastModified();
716 $s .= " " . wfMsg( "gnunote" );
717 return $s;
718 }
719
720 function lastModified()
721 {
722 global $wgLang, $wgArticle;
723
724 $timestamp = $wgArticle->getTimestamp();
725 if ( $timestamp ) {
726 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
727 $s = " " . wfMsg( "lastmodified", $d );
728 } else {
729 $s = "";
730 }
731 return $s;
732 }
733
734 function logoText( $align = "" )
735 {
736 if ( "" != $align ) { $a = " align='{$align}'"; }
737 else { $a = ""; }
738
739 $mp = wfMsg( "mainpage" );
740 $titleObj = Title::newFromText( $mp );
741 $s = "<a href=\"" . $titleObj->escapeLocalURL()
742 . "\"><img{$a} src=\""
743 . $this->getLogo() . "\" alt=\"" . "[{$mp}]\" /></a>";
744 return $s;
745 }
746
747 function quickBar()
748 {
749 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
750 global $wgDisableUploads, $wgRemoteUploads;
751
752 $fname = "Skin::quickBar";
753 wfProfileIn( $fname );
754
755 $action = $wgRequest->getText( 'action' );
756 $wpPreview = $wgRequest->getBool( 'wpPreview' );
757 $tns=$wgTitle->getNamespace();
758
759 $s = "\n<div id='quickbar'>";
760 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
761
762 $sep = "\n<br />";
763 $s .= $this->mainPageLink()
764 . $sep . $this->specialLink( "recentchanges" )
765 . $sep . $this->specialLink( "randompage" );
766 if ($wgUser->getID()) {
767 $s.= $sep . $this->specialLink( "watchlist" ) ;
768 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
769 wfMsg( "mycontris" ), "target=" . wfUrlencode($wgUser->getName() ) );
770
771 }
772 // only show watchlist link if logged in
773 if ( wfMsg ( "currentevents" ) != "" ) $s .= $sep . $this->makeKnownLink( wfMsg( "currentevents" ), "" ) ;
774 $s .= "\n<br /><hr class='sep' />";
775 $articleExists = $wgTitle->getArticleId();
776 if ( $wgOut->isArticle() || $action =="edit" || $action =="history" || $wpPreview) {
777 if($wgOut->isArticle()) {
778 $s .= "<strong>" . $this->editThisPage() . "</strong>";
779 } else { # backlink to the article in edit or history mode
780 if($articleExists){ # no backlink if no article
781 switch($tns) {
782 case 0:
783 $text = wfMsg("articlepage");
784 break;
785 case 1:
786 $text = wfMsg("viewtalkpage");
787 break;
788 case 2:
789 $text = wfMsg("userpage");
790 break;
791 case 3:
792 $text = wfMsg("viewtalkpage");
793 break;
794 case 4:
795 $text = wfMsg("wikipediapage");
796 break;
797 case 5:
798 $text = wfMsg("viewtalkpage");
799 break;
800 case 6:
801 $text = wfMsg("imagepage");
802 break;
803 case 7:
804 $text = wfMsg("viewtalkpage");
805 break;
806 default:
807 $text= wfMsg("articlepage");
808 }
809
810 $link = $wgTitle->getText();
811 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
812 $link = $nstext . ":" . $link ;
813 }
814
815 $s .= $this->makeLink( $link, $text );
816 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
817 # we just throw in a "New page" text to tell the user that he's in edit mode,
818 # and to avoid messing with the separator that is prepended to the next item
819 $s .= "<strong>" . wfMsg("newpage") . "</strong>";
820 }
821
822 }
823
824
825 if( $tns%2 && $action!="edit" && !$wpPreview) {
826 $s.="<br />".$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg("postcomment"),"action=edit&section=new");
827 }
828
829 /*
830 watching could cause problems in edit mode:
831 if user edits article, then loads "watch this article" in background and then saves
832 article with "Watch this article" checkbox disabled, the article is transparently
833 unwatched. Therefore we do not show the "Watch this page" link in edit mode
834 */
835 if ( 0 != $wgUser->getID() && $articleExists) {
836 if($action!="edit" && $action != "submit" )
837 {
838 $s .= $sep . $this->watchThisPage();
839 }
840 if ( $wgTitle->userCanEdit() )
841 $s .= $sep . $this->moveThisPage();
842 }
843 if ( $wgUser->isSysop() and $articleExists ) {
844 $s .= $sep . $this->deleteThisPage() .
845 $sep . $this->protectThisPage();
846 }
847 $s .= $sep . $this->talkLink();
848 if ($articleExists && $action !="history") {
849 $s .= $sep . $this->historyLink();
850 }
851 $s.=$sep . $this->whatLinksHere();
852
853 if($wgOut->isArticleRelated()) {
854 $s .= $sep . $this->watchPageLinksLink();
855 }
856
857 if ( Namespace::getUser() == $wgTitle->getNamespace()
858 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
859 ) {
860
861 $id=User::idFromName($wgTitle->getText());
862 $ip=User::isIP($wgTitle->getText());
863
864 if($id||$ip) {
865 $s .= $sep . $this->userContribsLink();
866 }
867 if ( 0 != $wgUser->getID() ) {
868 if($id) { # can only email real users
869 $s .= $sep . $this->emailUserLink();
870 }
871 }
872 }
873 $s .= "\n<br /><hr class='sep' />";
874 }
875
876 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
877 $s .= $this->specialLink( "upload" ) . $sep;
878 }
879 $s .= $this->specialLink( "specialpages" )
880 . $sep . $this->bugReportsLink();
881
882 global $wgSiteSupportPage;
883 if( $wgSiteSupportPage ) {
884 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
885 "\" class=\"internal\">" . wfMsg( "sitesupport" ) . "</a>";
886 }
887
888 $s .= "\n<br /></div>\n";
889 wfProfileOut( $fname );
890 return $s;
891 }
892
893 function specialPagesList()
894 {
895 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
896 $a = array();
897
898 $validSP = $wgLang->getValidSpecialPages();
899
900 foreach ( $validSP as $name => $desc ) {
901 if ( "" == $desc ) { continue; }
902 $a[$name] = $desc;
903 }
904 if ( $wgUser->isSysop() )
905 {
906 $sysopSP = $wgLang->getSysopSpecialPages();
907
908 foreach ( $sysopSP as $name => $desc ) {
909 if ( "" == $desc ) { continue; }
910 $a[$name] = $desc ;
911 }
912 }
913 if ( $wgUser->isDeveloper() )
914 {
915 $devSP = $wgLang->getDeveloperSpecialPages();
916
917 foreach ( $devSP as $name => $desc ) {
918 if ( "" == $desc ) { continue; }
919 $a[$name] = $desc ;
920 }
921 }
922 $go = wfMsg( "go" );
923 $sp = wfMsg( "specialpages" );
924 $spp = $wgLang->specialPage( "Specialpages" );
925
926 $s = "<form id=\"specialpages\" method=\"get\" class=\"inline\" " .
927 "action=\"{$wgServer}{$wgRedirectScript}\">\n";
928 $s .= "<select name=\"wpDropdown\">\n";
929 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
930
931 foreach ( $a as $name => $desc ) {
932 $p = $wgLang->specialPage( $name );
933 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
934 }
935 $s .= "</select>\n";
936 $s .= "<input type=submit value=\"{$go}\" name=redirect>\n";
937 $s .= "</form>\n";
938 return $s;
939 }
940
941 function mainPageLink()
942 {
943 $mp = wfMsg( "mainpage" );
944 $s = $this->makeKnownLink( $mp, $mp );
945 return $s;
946 }
947
948 function copyrightLink()
949 {
950 $s = $this->makeKnownLink( wfMsg( "copyrightpage" ),
951 wfMsg( "copyrightpagename" ) );
952 return $s;
953 }
954
955 function aboutLink()
956 {
957 $s = $this->makeKnownLink( wfMsg( "aboutpage" ),
958 wfMsg( "aboutwikipedia" ) );
959 return $s;
960 }
961
962
963 function disclaimerLink()
964 {
965 $s = $this->makeKnownLink( wfMsg( "disclaimerpage" ),
966 wfMsg( "disclaimers" ) );
967 return $s;
968 }
969
970 function editThisPage()
971 {
972 global $wgOut, $wgTitle, $wgRequest;
973
974 $oldid = $wgRequest->getVal( 'oldid' );
975 $diff = $wgRequest->getVal( 'diff' );
976 $redirect = $wgRequest->getVal( 'redirect' );
977
978 if ( ! $wgOut->isArticleRelated() ) {
979 $s = wfMsg( "protectedpage" );
980 } else {
981 $n = $wgTitle->getPrefixedText();
982 if ( $wgTitle->userCanEdit() ) {
983 $t = wfMsg( "editthispage" );
984 } else {
985 #$t = wfMsg( "protectedpage" );
986 $t = wfMsg( "viewsource" );
987 }
988 $oid = $red = "";
989
990 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
991 if ( $oldid && ! isset( $diff ) ) {
992 $oid = "&oldid={$oldid}";
993 }
994 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
995 }
996 return $s;
997 }
998
999 function deleteThisPage()
1000 {
1001 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1002
1003 $diff = $wgRequest->getVal( 'diff' );
1004 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1005 $n = $wgTitle->getPrefixedText();
1006 $t = wfMsg( "deletethispage" );
1007
1008 $s = $this->makeKnownLink( $n, $t, "action=delete" );
1009 } else {
1010 $s = "";
1011 }
1012 return $s;
1013 }
1014
1015 function protectThisPage()
1016 {
1017 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1018
1019 $diff = $wgRequest->getVal( 'diff' );
1020 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1021 $n = $wgTitle->getPrefixedText();
1022
1023 if ( $wgTitle->isProtected() ) {
1024 $t = wfMsg( "unprotectthispage" );
1025 $q = "action=unprotect";
1026 } else {
1027 $t = wfMsg( "protectthispage" );
1028 $q = "action=protect";
1029 }
1030 $s = $this->makeKnownLink( $n, $t, $q );
1031 } else {
1032 $s = "";
1033 }
1034 return $s;
1035 }
1036
1037 function watchThisPage()
1038 {
1039 global $wgUser, $wgOut, $wgTitle;
1040
1041 if ( $wgOut->isArticleRelated() ) {
1042 $n = $wgTitle->getPrefixedText();
1043
1044 if ( $wgTitle->userIsWatching() ) {
1045 $t = wfMsg( "unwatchthispage" );
1046 $q = "action=unwatch";
1047 } else {
1048 $t = wfMsg( "watchthispage" );
1049 $q = "action=watch";
1050 }
1051 $s = $this->makeKnownLink( $n, $t, $q );
1052 } else {
1053 $s = wfMsg( "notanarticle" );
1054 }
1055 return $s;
1056 }
1057
1058 function moveThisPage()
1059 {
1060 global $wgTitle, $wgLang;
1061
1062 if ( $wgTitle->userCanEdit() ) {
1063 $s = $this->makeKnownLink( $wgLang->specialPage( "Movepage" ),
1064 wfMsg( "movethispage" ), "target=" . $wgTitle->getPrefixedURL() );
1065 } // no message if page is protected - would be redundant
1066 return $s;
1067 }
1068
1069 function historyLink()
1070 {
1071 global $wgTitle;
1072
1073 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1074 wfMsg( "history" ), "action=history" );
1075 return $s;
1076 }
1077
1078 function whatLinksHere()
1079 {
1080 global $wgTitle, $wgLang;
1081
1082 $s = $this->makeKnownLink( $wgLang->specialPage( "Whatlinkshere" ),
1083 wfMsg( "whatlinkshere" ), "target=" . $wgTitle->getPrefixedURL() );
1084 return $s;
1085 }
1086
1087 function userContribsLink()
1088 {
1089 global $wgTitle, $wgLang;
1090
1091 $s = $this->makeKnownLink( $wgLang->specialPage( "Contributions" ),
1092 wfMsg( "contributions" ), "target=" . $wgTitle->getPartialURL() );
1093 return $s;
1094 }
1095
1096 function emailUserLink()
1097 {
1098 global $wgTitle, $wgLang;
1099
1100 $s = $this->makeKnownLink( $wgLang->specialPage( "Emailuser" ),
1101 wfMsg( "emailuser" ), "target=" . $wgTitle->getPartialURL() );
1102 return $s;
1103 }
1104
1105 function watchPageLinksLink()
1106 {
1107 global $wgOut, $wgTitle, $wgLang;
1108
1109 if ( ! $wgOut->isArticleRelated() ) {
1110 $s = "(" . wfMsg( "notanarticle" ) . ")";
1111 } else {
1112 $s = $this->makeKnownLink( $wgLang->specialPage(
1113 "Recentchangeslinked" ), wfMsg( "recentchangeslinked" ),
1114 "target=" . $wgTitle->getPrefixedURL() );
1115 }
1116 return $s;
1117 }
1118
1119 function otherLanguages()
1120 {
1121 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1122
1123 $a = $wgOut->getLanguageLinks();
1124 if ( 0 == count( $a ) ) {
1125 if ( !$wgUseNewInterlanguage ) return "";
1126 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1127 if ( $ns != 0 AND $ns != 1 ) return "" ;
1128 $pn = "Intl" ;
1129 $x = "mode=addlink&xt=".$wgTitle->getDBkey() ;
1130 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1131 wfMsg( "intl" ) , $x );
1132 }
1133
1134 if ( !$wgUseNewInterlanguage ) {
1135 $s = wfMsg( "otherlanguages" ) . ": ";
1136 } else {
1137 global $wgLanguageCode ;
1138 $x = "mode=zoom&xt=".$wgTitle->getDBkey() ;
1139 $x .= "&xl=".$wgLanguageCode ;
1140 $s = $this->makeKnownLink( $wgLang->specialPage( "Intl" ),
1141 wfMsg( "otherlanguages" ) , $x ) . ": " ;
1142 }
1143
1144 $s = wfMsg( "otherlanguages" ) . ": ";
1145 $first = true;
1146 if($wgLang->isRTL()) $s .= "<span dir='LTR'>";
1147 foreach( $a as $l ) {
1148 if ( ! $first ) { $s .= " | "; }
1149 $first = false;
1150
1151 $nt = Title::newFromText( $l );
1152 $url = $nt->getFullURL();
1153 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1154
1155 if ( "" == $text ) { $text = $l; }
1156 $style = $this->getExternalLinkAttributes( $l, $text );
1157 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1158 }
1159 if($wgLang->isRTL()) $s .= "</span>";
1160 return $s;
1161 }
1162
1163 function bugReportsLink()
1164 {
1165 $s = $this->makeKnownLink( wfMsg( "bugreportspage" ),
1166 wfMsg( "bugreports" ) );
1167 return $s;
1168 }
1169
1170 function dateLink()
1171 {
1172 global $wgLinkCache;
1173 $t1 = Title::newFromText( gmdate( "F j" ) );
1174 $t2 = Title::newFromText( gmdate( "Y" ) );
1175
1176 $wgLinkCache->suspend();
1177 $id = $t1->getArticleID();
1178 $wgLinkCache->resume();
1179
1180 if ( 0 == $id ) {
1181 $s = $this->makeBrokenLink( $t1->getText() );
1182 } else {
1183 $s = $this->makeKnownLink( $t1->getText() );
1184 }
1185 $s .= ", ";
1186
1187 $wgLinkCache->suspend();
1188 $id = $t2->getArticleID();
1189 $wgLinkCache->resume();
1190
1191 if ( 0 == $id ) {
1192 $s .= $this->makeBrokenLink( $t2->getText() );
1193 } else {
1194 $s .= $this->makeKnownLink( $t2->getText() );
1195 }
1196 return $s;
1197 }
1198
1199 function talkLink()
1200 {
1201 global $wgLang, $wgTitle, $wgLinkCache;
1202
1203 $tns = $wgTitle->getNamespace();
1204 if ( -1 == $tns ) { return ""; }
1205
1206 $pn = $wgTitle->getText();
1207 $tp = wfMsg( "talkpage" );
1208 if ( Namespace::isTalk( $tns ) ) {
1209 $lns = Namespace::getSubject( $tns );
1210 switch($tns) {
1211 case 1:
1212 $text = wfMsg("articlepage");
1213 break;
1214 case 3:
1215 $text = wfMsg("userpage");
1216 break;
1217 case 5:
1218 $text = wfMsg("wikipediapage");
1219 break;
1220 case 7:
1221 $text = wfMsg("imagepage");
1222 break;
1223 default:
1224 $text= wfMsg("articlepage");
1225 }
1226 } else {
1227
1228 $lns = Namespace::getTalk( $tns );
1229 $text=$tp;
1230 }
1231 $n = $wgLang->getNsText( $lns );
1232 if ( "" == $n ) { $link = $pn; }
1233 else { $link = "{$n}:{$pn}"; }
1234
1235 $wgLinkCache->suspend();
1236 $s = $this->makeLink( $link, $text );
1237 $wgLinkCache->resume();
1238
1239 return $s;
1240 }
1241
1242 function commentLink()
1243 {
1244 global $wgLang, $wgTitle, $wgLinkCache;
1245
1246 $tns = $wgTitle->getNamespace();
1247 if ( -1 == $tns ) { return ""; }
1248
1249 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1250
1251 # assert Namespace::isTalk( $lns )
1252
1253 $n = $wgLang->getNsText( $lns );
1254 $pn = $wgTitle->getText();
1255
1256 $link = "{$n}:{$pn}";
1257
1258 $wgLinkCache->suspend();
1259 $s = $this->makeKnownLink($link, wfMsg("postcomment"), "action=edit&section=new");
1260 $wgLinkCache->resume();
1261
1262 return $s;
1263 }
1264
1265 # After all the page content is transformed into HTML, it makes
1266 # a final pass through here for things like table backgrounds.
1267 #
1268 function transformContent( $text )
1269 {
1270 return $text;
1271 }
1272
1273 # Note: This function MUST call getArticleID() on the link,
1274 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1275 #
1276 function makeLink( $title, $text = "", $query = "", $trail = "" ) {
1277 wfProfileIn( "Skin::makeLink" );
1278 $nt = Title::newFromText( $title );
1279 if ($nt) {
1280 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1281 } else {
1282 wfDebug( "Invalid title passed to Skin::makeLink(): \"$title\"\n" );
1283 $result = $text == "" ? $title : $text;
1284 }
1285
1286 wfProfileOut( "Skin::makeLink" );
1287 return $result;
1288 }
1289
1290 function makeKnownLink( $title, $text = "", $query = "", $trail = "", $prefix = '',$aprops = '') {
1291 $nt = Title::newFromText( $title );
1292 if ($nt) {
1293 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1294 } else {
1295 wfDebug( "Invalid title passed to Skin::makeKnownLink(): \"$title\"\n" );
1296 return $text == "" ? $title : $text;
1297 }
1298 }
1299
1300 function makeBrokenLink( $title, $text = "", $query = "", $trail = "" ) {
1301 $nt = Title::newFromText( $title );
1302 if ($nt) {
1303 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1304 } else {
1305 wfDebug( "Invalid title passed to Skin::makeBrokenLink(): \"$title\"\n" );
1306 return $text == "" ? $title : $text;
1307 }
1308 }
1309
1310 function makeStubLink( $title, $text = "", $query = "", $trail = "" ) {
1311 $nt = Title::newFromText( $title );
1312 if ($nt) {
1313 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1314 } else {
1315 wfDebug( "Invalid title passed to Skin::makeStubLink(): \"$title\"\n" );
1316 return $text == "" ? $title : $text;
1317 }
1318 }
1319
1320 # Pass a title object, not a title string
1321 function makeLinkObj( &$nt, $text= "", $query = "", $trail = "", $prefix = "" )
1322 {
1323 global $wgOut, $wgUser;
1324 if ( $nt->isExternal() ) {
1325 $u = $nt->getFullURL();
1326 $link = $nt->getPrefixedURL();
1327 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1328 $style = $this->getExternalLinkAttributes( $link, $text );
1329
1330 $inside = "";
1331 if ( "" != $trail ) {
1332 if ( preg_match( "/^([a-z]+)(.*)$$/sD", $trail, $m ) ) {
1333 $inside = $m[1];
1334 $trail = $m[2];
1335 }
1336 }
1337 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1338 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1339 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1340 } elseif ( ( -1 == $nt->getNamespace() ) ||
1341 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1342 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1343 } else {
1344 $aid = $nt->getArticleID() ;
1345 if ( 0 == $aid ) {
1346 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1347 } else {
1348 $threshold = $wgUser->getOption("stubthreshold") ;
1349 if ( $threshold > 0 ) {
1350 $res = wfQuery ( "SELECT LENGTH(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ ) ;
1351
1352 if ( wfNumRows( $res ) > 0 ) {
1353 $s = wfFetchObject( $res );
1354 $size = $s->x;
1355 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1356 $size = $threshold*2 ; # Really big
1357 }
1358 wfFreeResult( $res );
1359 } else {
1360 $size = $threshold*2 ; # Really big
1361 }
1362 } else {
1363 $size = 1 ;
1364 }
1365 if ( $size < $threshold ) {
1366 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1367 } else {
1368 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1369 }
1370 }
1371 }
1372 return $retVal;
1373 }
1374
1375 # Pass a title object, not a title string
1376 function makeKnownLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" , $aprops = '')
1377 {
1378 global $wgOut, $wgTitle;
1379
1380 $fname = "Skin::makeKnownLinkObj";
1381 wfProfileIn( $fname );
1382
1383 $link = $nt->getPrefixedURL();
1384
1385 if ( "" == $link ) {
1386 $u = "";
1387 if ( "" == $text ) { $text = $nt->getFragment(); }
1388 } else {
1389 $u = $nt->escapeLocalURL( $query );
1390 }
1391 if ( "" != $nt->getFragment() ) {
1392 $u .= "#" . wfEscapeHTML( $nt->getFragment() );
1393 }
1394 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1395 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1396
1397 $inside = "";
1398 if ( "" != $trail ) {
1399 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1400 $inside = $m[1];
1401 $trail = $m[2];
1402 }
1403 }
1404 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1405 wfProfileOut( $fname );
1406 return $r;
1407 }
1408
1409 # Pass a title object, not a title string
1410 function makeBrokenLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" )
1411 {
1412 global $wgOut, $wgUser;
1413
1414 $fname = "Skin::makeBrokenLinkObj";
1415 wfProfileIn( $fname );
1416
1417 if ( "" == $query ) {
1418 $q = "action=edit";
1419 } else {
1420 $q = "action=edit&{$query}";
1421 }
1422 $u = $nt->escapeLocalURL( $q );
1423
1424 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1425 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1426
1427 $inside = "";
1428 if ( "" != $trail ) {
1429 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1430 $inside = $m[1];
1431 $trail = $m[2];
1432 }
1433 }
1434 if ( $wgUser->getOption( "highlightbroken" ) ) {
1435 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1436 } else {
1437 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1438 }
1439
1440 wfProfileOut( $fname );
1441 return $s;
1442 }
1443
1444 # Pass a title object, not a title string
1445 function makeStubLinkObj( &$nt, $text = "", $query = "", $trail = "", $prefix = "" )
1446 {
1447 global $wgOut, $wgUser;
1448
1449 $link = $nt->getPrefixedURL();
1450
1451 $u = $nt->escapeLocalURL( $query );
1452
1453 if ( "" == $text ) { $text = $nt->getPrefixedText(); }
1454 $style = $this->getInternalLinkAttributesObj( $nt, $text, "stub" );
1455
1456 $inside = "";
1457 if ( "" != $trail ) {
1458 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1459 $inside = $m[1];
1460 $trail = $m[2];
1461 }
1462 }
1463 if ( $wgUser->getOption( "highlightbroken" ) ) {
1464 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1465 } else {
1466 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1467 }
1468 return $s;
1469 }
1470
1471 function fnamePart( $url )
1472 {
1473 $basename = strrchr( $url, "/" );
1474 if ( false === $basename ) { $basename = $url; }
1475 else { $basename = substr( $basename, 1 ); }
1476 return wfEscapeHTML( $basename );
1477 }
1478
1479 function makeImage( $url, $alt = "" )
1480 {
1481 global $wgOut;
1482
1483 if ( "" == $alt ) { $alt = $this->fnamePart( $url ); }
1484 $s = "<img src=\"{$url}\" alt=\"{$alt}\" />";
1485 return $s;
1486 }
1487
1488 function makeImageLink( $name, $url, $alt = "" ) {
1489 $nt = Title::makeTitle( Namespace::getImage(), $name );
1490 return $this->makeImageLinkObj( $nt, $alt );
1491 }
1492
1493 function makeImageLinkObj( $nt, $alt = "" ) {
1494 global $wgLang, $wgUseImageResize;
1495 $name = $nt->getDBKey();
1496 $url = wfImageUrl( $name );
1497 $align = "";
1498 $prefix = $postfix = "";
1499
1500 if ( $wgUseImageResize ) {
1501 # Check if the alt text is of the form "options|alt text"
1502 # Options are:
1503 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1504 # * left no resizing, just left align. label is used for alt= only
1505 # * right same, but right aligned
1506 # * none same, but not aligned
1507 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1508
1509 $part = explode( "|", $alt);
1510
1511 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1512 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1513 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1514 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1515 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1516 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1517 $alt = $part[count($part)-1];
1518
1519 $thumb=false;
1520
1521 foreach( $part as $key => $val ) {
1522 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1523 $thumb=true;
1524 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1525 # remember to set an alignment, don't render immediately
1526 $align = "right";
1527 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1528 # remember to set an alignment, don't render immediately
1529 $align = "left";
1530 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1531 # remember to set an alignment, don't render immediately
1532 $align = "center";
1533 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1534 # remember to set an alignment, don't render immediately
1535 $align = "none";
1536 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1537 # $match is the image width in pixels
1538 $width = intval($match);
1539 }
1540 }
1541 if ( "center" == $align )
1542 {
1543 $prefix = '<span style="text-align: center">';
1544 $postfix = '</span>';
1545 $align = "none";
1546 }
1547
1548 if ( $thumb ) {
1549
1550 # Create a thumbnail. Alignment depends on language
1551 # writing direction, # right aligned for left-to-right-
1552 # languages ("Western languages"), left-aligned
1553 # for right-to-left-languages ("Semitic languages")
1554 #
1555 # If thumbnail width has not been provided, it is set
1556 # here to 180 pixels
1557 if ( $align == "" ) {
1558 $align = $wgLang->isRTL() ? "left" : "right";
1559 }
1560 if ( ! isset($width) ) {
1561 $width = 180;
1562 }
1563 return $prefix.$this->makeThumbLinkObj( $nt, $alt, $align, $width ).$postfix;
1564
1565 } elseif ( isset($width) ) {
1566
1567 # Create a resized image, without the additional thumbnail
1568 # features
1569 $url = $this->createThumb( $name, $width );
1570 }
1571 } # endif $wgUseImageResize
1572
1573 if ( empty( $alt ) ) {
1574 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1575 }
1576 $alt = htmlspecialchars( $alt );
1577
1578 $u = $nt->escapeLocalURL();
1579 if ( $url == "" )
1580 {
1581 $s = str_replace( "$1", $name, wfMsg("missingimage") );
1582 } else {
1583 $s = "<a href=\"{$u}\" class='image' title=\"{$alt}\">" .
1584 "<img src=\"{$url}\" alt=\"{$alt}\" /></a>";
1585 }
1586 if ( "" != $align ) {
1587 $s = "<div class=\"float{$align}\"><span>{$s}</span>\n</div>";
1588 }
1589 return $prefix.$s.$postfix;
1590 }
1591
1592 function createThumb( $name, $width ) {
1593 global $wgUploadDirectory;
1594 global $wgImageMagickConvertCommand;
1595 global $wgUseImageMagick;
1596 global $wgUseSquid, $wgInternalServer;
1597 $imgPath = wfImagePath( $name );
1598 $thumbName = $width."px-".$name;
1599 $thumbPath = wfImageThumbDir( $thumbName )."/".$thumbName;
1600 $thumbUrl = wfImageThumbUrl( $thumbName );
1601
1602 if ( ! file_exists( $imgPath ) )
1603 {
1604 # If there is no image, there will be no thumbnail
1605 return "";
1606 }
1607
1608 if ( (! file_exists( $thumbPath ) )
1609 || ( filemtime($thumbPath) < filemtime($imgPath) ) ) {
1610 # Squid purging
1611 if ( $wgUseSquid ) {
1612 $urlArr = Array(
1613 $wgInternalServer.$thumbUrl
1614 );
1615 wfPurgeSquidServers($urlArr);
1616 }
1617
1618 if ( $wgUseImageMagick ) {
1619 # use ImageMagick
1620 $cmd = $wgImageMagickConvertCommand .
1621 " -quality 85 -geometry {$width} ".
1622 escapeshellarg($imgPath) . " " .
1623 escapeshellarg($thumbPath);
1624 $conv = shell_exec( $cmd );
1625 } else {
1626 # Use PHP's builtin GD library functions.
1627 #
1628 # First find out what kind of file this is, and select the correct
1629 # input routine for this.
1630 list($src_width, $src_height, $src_type, $src_attr) = getimagesize( $imgPath );
1631 switch( $src_type ) {
1632 case 1: # GIF
1633 $src_image = imagecreatefromgif( $imgPath );
1634 break;
1635 case 2: # JPG
1636 $src_image = imagecreatefromjpeg( $imgPath );
1637 break;
1638 case 3: # PNG
1639 $src_image = imagecreatefrompng( $imgPath );
1640 break;
1641 case 15: # WBMP for WML
1642 $src_image = imagecreatefromwbmp( $imgPath );
1643 break;
1644 case 16: # XBM
1645 $src_image = imagecreatefromxbm( $imgPath );
1646 break;
1647 default:
1648 return "Image type not supported";
1649 break;
1650 }
1651 $height = floor( $src_height * ( $width/$src_width ) );
1652 $dst_image = imagecreatetruecolor( $width, $height );
1653 imagecopyresampled( $dst_image, $src_image,
1654 0,0,0,0,
1655 $width, $height, $src_width, $src_height );
1656 switch( $src_type ) {
1657 case 1: # GIF
1658 case 3: # PNG
1659 case 15: # WBMP
1660 case 16: # XBM
1661 #$thumbUrl .= ".png";
1662 #$thumbPath .= ".png";
1663 imagepng( $dst_image, $thumbPath );
1664 break;
1665 case 2: # JPEG
1666 #$thumbUrl .= ".jpg";
1667 #$thumbPath .= ".jpg";
1668 imageinterlace( $dst_image );
1669 imagejpeg( $dst_image, $thumbPath, 95 );
1670 break;
1671 default:
1672 break;
1673 }
1674 imagedestroy( $dst_image );
1675 imagedestroy( $src_image );
1676
1677
1678 }
1679 #
1680 # Check for zero-sized thumbnails. Those can be generated when
1681 # no disk space is available or some other error occurs
1682 #
1683 $thumbstat = stat( $thumbPath );
1684 $imgstat = stat( $imgPath );
1685 if( $thumbstat["size"] == 0 )
1686 {
1687 unlink( $thumbPath );
1688 }
1689
1690 }
1691 return $thumbUrl;
1692 }
1693
1694 function makeThumbLinkObj( $nt, $label = "", $align = "right", $boxwidth = 180 ) {
1695 global $wgUploadPath, $wgLang;
1696 $name = $nt->getDBKey();
1697 $image = Title::makeTitle( Namespace::getImage(), $name );
1698 $url = wfImageUrl( $name );
1699 $path = wfImagePath( $name );
1700
1701 #$label = htmlspecialchars( $label );
1702 $alt = preg_replace( "/<[^>]*>/", "", $label);
1703 $alt = htmlspecialchars( $alt );
1704
1705 if ( file_exists( $path ) )
1706 {
1707 list($width, $height, $type, $attr) = getimagesize( $path );
1708 } else {
1709 $width = $height = 200;
1710 }
1711 $boxheight = intval( $height/($width/$boxwidth) );
1712 if ( $boxwidth > $width ) {
1713 $boxwidth = $width;
1714 $boxheight = $height;
1715 }
1716
1717 $thumbUrl = $this->createThumb( $name, $boxwidth );
1718
1719 $u = $nt->escapeLocalURL();
1720
1721 $more = htmlspecialchars( wfMsg( "thumbnail-more" ) );
1722 $magnifyalign = $wgLang->isRTL() ? "left" : "right";
1723 $textalign = $wgLang->isRTL() ? " style=\"text-align:right\"" : "";
1724
1725 $s = "<div class=\"thumbnail-{$align}\" style=\"width:{$boxwidth}px;\"><div>";
1726 if ( $thumbUrl == "" ) {
1727 $s .= str_replace( "$1", $name, wfMsg("missingimage") );
1728 } else {
1729 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1730 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1731 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>'.
1732 '<a href="'.$u.'" class="internal" title="'.$more.'"> '.
1733 '<img src="'.$wgUploadPath.'/magnify-clip.png" ' .
1734 'width="26" height="24" align="'.$magnifyalign.'" alt="'.$more.'" /> </a>';
1735 }
1736 $s .= ' <div'.$textalign.'>'.$label."</div></div>\n</div>";
1737 return $s;
1738 }
1739
1740 function makeMediaLink( $name, $url, $alt = "" ) {
1741 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1742 return $this->makeMediaLinkObj( $nt, $alt );
1743 }
1744
1745 function makeMediaLinkObj( $nt, $alt = "" )
1746 {
1747 $name = $nt->getDBKey();
1748 $url = wfImageUrl( $name );
1749 if ( empty( $alt ) ) {
1750 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1751 }
1752
1753 $u = htmlspecialchars( $url );
1754 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1755 return $s;
1756 }
1757
1758 function specialLink( $name, $key = "" )
1759 {
1760 global $wgLang;
1761
1762 if ( "" == $key ) { $key = strtolower( $name ); }
1763 $pn = $wgLang->ucfirst( $name );
1764 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1765 wfMsg( $key ) );
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' tabindex='4000000'>\");\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.="/*]]>*/</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 ?>