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