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