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