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