Be a little more careful about escaping displayed usernames
[mediawiki.git] / includes / Skin.php
blob3d9f13874f177582ca7d2a82fb2e0193b009a1cd
1 <?php
2 # See skin.doc
4 require_once( 'Feed.php' ); // should not be called if the actual page isn't feed enabled
5 require_once( 'Image.php' );
7 # These are the INTERNAL names, which get mapped
8 # directly to class names. For display purposes, the
9 # Language class has internationalized names
11 /* private */ $wgValidSkinNames = array(
12 'standard' => 'Standard',
13 'nostalgia' => 'Nostalgia',
14 'cologneblue' => 'CologneBlue'
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';
25 require_once( 'RecentChange.php' );
27 class RCCacheEntry extends RecentChange
29 var $secureName, $link;
30 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
31 var $userlink, $timestamp, $watched;
33 function newFromParent( $rc )
35 $rc2 = new RCCacheEntry;
36 $rc2->mAttribs = $rc->mAttribs;
37 $rc2->mExtra = $rc->mExtra;
38 return $rc2;
40 } ;
42 class Skin {
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;
50 function Skin()
52 $this->linktrail = wfMsg('linktrail');
55 function getSkinNames()
57 global $wgValidSkinNames;
58 return $wgValidSkinNames;
61 function getStylesheet()
63 return 'wikistandard.css';
65 function getSkinName() {
66 return "standard";
69 function qbSetting()
71 global $wgOut, $wgUser;
73 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
74 $q = $wgUser->getOption( 'quickbar' );
75 if ( '' == $q ) { $q = 0; }
76 return $q;
79 function initPage( &$out )
81 $fname = 'Skin::initPage';
82 wfProfileIn( $fname );
84 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
86 $this->addMetadataLinks($out);
88 wfProfileOut( $fname );
91 function addMetadataLinks( &$out ) {
92 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
93 global $wgRightsPage, $wgRightsUrl;
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') ) );
103 if( $wgEnableDublinCoreRdf ) {
104 $out->addMetadataLink( array(
105 'title' => 'Dublin Core',
106 'type' => 'application/rdf+xml',
107 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
110 $copyright = '';
111 if( $wgRightsPage ) {
112 $copy = Title::newFromText( $wgRightsPage );
113 if( $copy ) {
114 $copyright = $copy->getLocalURL();
117 if( !$copyright && $wgRightsUrl ) {
118 $copyright = $wgRightsUrl;
120 if( $copyright ) {
121 $out->addLink( array(
122 'rel' => 'copyright',
123 'href' => $copyright ) );
127 function outputPage( &$out ) {
128 global $wgDebugComments;
130 wfProfileIn( 'Skin::outputPage' );
131 $this->initPage( $out );
132 $out->out( $out->headElement() );
134 $out->out( "\n<body" );
135 $ops = $this->getBodyOptions();
136 foreach ( $ops as $name => $val ) {
137 $out->out( " $name='$val'" );
139 $out->out( ">\n" );
140 if ( $wgDebugComments ) {
141 $out->out( "<!-- Wiki debugging output:\n" .
142 $out->mDebugtext . "-->\n" );
144 $out->out( $this->beforeContent() );
146 $out->out( $out->mBodytext . "\n" );
148 $out->out( $this->afterContent() );
150 wfProfileClose();
151 $out->out( $out->reportTime() );
153 $out->out( "\n</body></html>" );
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";
164 return $r;
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";
182 $s .= $this->doGetUserStyles();
183 return $s."\n";
185 # placeholder, returns generated js in monobook
186 function getUserJs() {
187 return;
190 function getUserStyles()
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;
201 function doGetUserStyles()
203 global $wgUser;
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";
214 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
215 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
217 if ( 1 == $wgUser->getOption( 'justify' ) ) {
218 $s .= "#article { text-align: justify; }\n";
220 return $s;
223 function getBodyOptions()
225 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
227 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
229 if ( 0 != $wgTitle->getNamespace() ) {
230 $a = array( 'bgcolor' => '#ffffec' );
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}";
240 if ( !empty($oldid) && ! isset( $diff ) ) {
241 $oid = "&oldid={$oldid}";
243 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
244 $s = 'document.location = "' .$s .'";';
245 $a += array ('ondblclick' => $s);
248 $a['onload'] = $wgOut->getOnloadHandler();
249 return $a;
252 function getExternalLinkAttributes( $link, $text, $class='' )
254 global $wgUser, $wgOut, $wgLang;
256 $link = urldecode( $link );
257 $link = $wgLang->checkTitleEncoding( $link );
258 $link = str_replace( '_', ' ', $link );
259 $link = wfEscapeHTML( $link );
261 $r = ($class != '') ? " class='$class'" : " class='external'";
263 if ( 1 == $wgUser->getOption( 'hover' ) ) {
264 $r .= " title=\"{$link}\"";
266 return $r;
269 function getInternalLinkAttributes( $link, $text, $broken = false )
271 global $wgUser, $wgOut;
273 $link = urldecode( $link );
274 $link = str_replace( '_', ' ', $link );
275 $link = wfEscapeHTML( $link );
277 if ( $broken == 'stub' ) {
278 $r = ' class="stub"';
279 } else if ( $broken == 'yes' ) {
280 $r = ' class="new"';
281 } else {
282 $r = '';
285 if ( 1 == $wgUser->getOption( 'hover' ) ) {
286 $r .= " title=\"{$link}\"";
288 return $r;
291 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
293 global $wgUser, $wgOut;
295 if ( $broken == 'stub' ) {
296 $r = ' class="stub"';
297 } else if ( $broken == 'yes' ) {
298 $r = ' class="new"';
299 } else {
300 $r = '';
303 if ( 1 == $wgUser->getOption( 'hover' ) ) {
304 $r .= ' title ="' . $nt->getEscapedText() . '"';
306 return $r;
309 function getLogo()
311 global $wgLogo;
312 return $wgLogo;
315 # This will be called immediately after the <body> tag. Split into
316 # two functions to make it easier to subclass.
318 function beforeContent()
320 global $wgUser, $wgOut, $wgSiteNotice;
322 if( $wgSiteNotice ) {
323 $note = "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
324 } else {
325 $note = '';
327 return $this->doBeforeContent() . $note;
330 function doBeforeContent()
332 global $wgUser, $wgOut, $wgTitle, $wgLang;
333 $fname = 'Skin::doBeforeContent';
334 wfProfileIn( $fname );
336 $s = '';
337 $qb = $this->qbSetting();
339 if( $langlinks = $this->otherLanguages() ) {
340 $rows = 2;
341 $borderhack = '';
342 } else {
343 $rows = 1;
344 $langlinks = false;
345 $borderhack = 'class="top"';
348 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
349 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
351 $shove = ($qb != 0);
352 $left = ($qb == 1 || $qb == 3);
353 if($wgLang->isRTL()) $left = !$left;
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 );
361 $l = $wgLang->isRTL() ? 'right' : 'left';
362 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
364 $s .= $this->topLinks() ;
365 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
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>";
372 if ( $langlinks ) {
373 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
376 if ( $shove && !$left ) { # Right
377 $s .= $this->getQuickbarCompensator( $rows );
379 $s .= "</tr>\n</table>\n</div>\n";
380 $s .= "\n<div id='article'>\n";
382 $s .= $this->pageTitle();
383 $s .= $this->pageSubtitle() ;
384 $s .= $this->getCategories();
385 wfProfileOut( $fname );
386 return $s;
389 function getCategoryLinks () {
390 global $wgOut, $wgTitle, $wgUser, $wgParser;
391 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
393 if( !$wgUseCategoryMagic ) return '' ;
394 if( count( $wgOut->mCategoryLinks ) == 0 ) return '';
396 # Taken out so that they will be displayed in previews -- TS
397 #if( !$wgOut->isArticle() ) return '';
399 $t = implode ( ' | ' , $wgOut->mCategoryLinks ) ;
400 $s = $this->makeKnownLink( 'Special:Categories',
401 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
402 . ': ' . $t;
404 if($wgUseCategoryBrowser) {
405 $s .= '<br/><hr/>';
406 $catstack = array();
407 $s.= $wgTitle->getAllParentCategories($catstack);
410 return $s;
413 function getCategories() {
414 $catlinks=$this->getCategoryLinks();
415 if(!empty($catlinks)) {
416 return "<p class='catlinks'>{$catlinks}</p>";
420 function getQuickbarCompensator( $rows = 1 )
422 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
425 # This gets called immediately before the </body> tag.
427 function afterContent()
429 global $wgUser, $wgOut, $wgServer;
430 global $wgTitle, $wgLang;
432 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
433 return $printfooter . $this->doAfterContent();
436 function printFooter() {
437 global $wgTitle;
438 $url = htmlspecialchars( $wgTitle->getFullURL() );
439 return "<p>" . wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" ) .
440 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
443 function doAfterContent()
445 global $wgUser, $wgOut, $wgLang;
446 $fname = 'Skin::doAfterContent';
447 wfProfileIn( $fname );
448 wfProfileIn( $fname.'-1' );
450 $s = "\n</div><br style=\"clear:both\" />\n";
451 $s .= "\n<div id='footer'>";
452 $s .= '<table border="0" cellspacing="0"><tr>';
454 wfProfileOut( $fname.'-1' );
455 wfProfileIn( $fname.'-2' );
457 $qb = $this->qbSetting();
458 $shove = ($qb != 0);
459 $left = ($qb == 1 || $qb == 3);
460 if($wgLang->isRTL()) $left = !$left;
462 if ( $shove && $left ) { # Left
463 $s .= $this->getQuickbarCompensator();
465 wfProfileOut( $fname.'-2' );
466 wfProfileIn( $fname.'-3' );
467 $l = $wgLang->isRTL() ? 'right' : 'left';
468 $s .= "<td class='bottom' align='$l' valign='top'>";
470 $s .= $this->bottomLinks();
471 $s .= "\n<br />" . $this->mainPageLink()
472 . ' | ' . $this->aboutLink()
473 . ' | ' . $this->specialLink( 'recentchanges' )
474 . ' | ' . $this->searchForm()
475 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
477 $s .= "</td>";
478 if ( $shove && !$left ) { # Right
479 $s .= $this->getQuickbarCompensator();
481 $s .= "</tr></table>\n</div>\n</div>\n";
483 wfProfileOut( $fname.'-3' );
484 wfProfileIn( $fname.'-4' );
485 if ( 0 != $qb ) { $s .= $this->quickBar(); }
486 wfProfileOut( $fname.'-4' );
487 wfProfileOut( $fname );
488 return $s;
491 function pageTitleLinks()
493 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
495 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
496 $action = $wgRequest->getText( 'action' );
498 $s = $this->printableLink();
499 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
501 if ( $wgOut->isArticleRelated() ) {
502 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
503 $name = $wgTitle->getDBkey();
504 $link = wfEscapeHTML( Image::wfImageUrl( $name ) );
505 $style = $this->getInternalLinkAttributes( $link, $name );
506 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
508 # This will show the "Approve" link if $wgUseApproval=true;
509 if ( isset ( $wgUseApproval ) && $wgUseApproval )
511 $t = $wgTitle->getDBkey();
512 $name = 'Approve this article' ;
513 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
514 #wfEscapeHTML( wfImageUrl( $name ) );
515 $style = $this->getExternalLinkAttributes( $link, $name );
516 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
519 if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) {
520 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
521 wfMsg( 'currentrev' ) );
524 if ( $wgUser->getNewtalk() ) {
525 # do not show "You have new messages" text when we are viewing our
526 # own talk page
528 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
529 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
530 $n =$wgUser->getName();
531 $tl = $this->makeKnownLink( $wgLang->getNsText(
532 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
533 wfMsg('newmessageslink') );
534 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
538 $undelete = $this->getUndeleteLink();
539 if( !empty( $undelete ) ) {
540 $s .= ' | '.$undelete;
542 return $s;
545 function getUndeleteLink() {
546 global $wgUser, $wgTitle, $wgLang, $action;
547 if( $wgUser->isSysop() &&
548 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
549 ($n = $wgTitle->isDeleted() ) ) {
550 return wfMsg( 'thisisdeleted',
551 $this->makeKnownLink(
552 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
553 wfMsg( 'restorelink', $n ) ) );
555 return '';
558 function printableLink()
560 global $wgOut, $wgFeedClasses, $wgRequest;
562 $baseurl = $_SERVER['REQUEST_URI'];
563 if( strpos( '?', $baseurl ) == false ) {
564 $baseurl .= '?';
565 } else {
566 $baseurl .= '&';
568 $baseurl = htmlspecialchars( $baseurl );
569 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
571 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
572 if( $wgOut->isSyndicated() ) {
573 foreach( $wgFeedClasses as $format => $class ) {
574 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
575 $s .= " | <a href=\"$feedurl\">{$format}</a>";
578 return $s;
581 function pageTitle()
583 global $wgOut, $wgTitle, $wgUser;
585 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
586 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
587 return $s;
590 function pageSubtitle()
592 global $wgOut;
594 $sub = $wgOut->getSubtitle();
595 if ( '' == $sub ) {
596 global $wgExtraSubtitle;
597 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
599 $subpages = $this->subPageSubtitle();
600 $sub .= !empty($subpages)?"</p><p class='subpages'>$subpages":'';
601 $s = "<p class='subtitle'>{$sub}</p>\n";
602 return $s;
605 function subPageSubtitle()
607 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
608 $subpages = '';
609 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
610 $ptext=$wgTitle->getPrefixedText();
611 if(preg_match('/\//',$ptext)) {
612 $links = explode('/',$ptext);
613 $c = 0;
614 $growinglink = '';
615 foreach($links as $link) {
616 $c++;
617 if ($c<count($links)) {
618 $growinglink .= $link;
619 $getlink = $this->makeLink( $growinglink, $link );
620 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
621 if ($c>1) {
622 $subpages .= ' | ';
623 } else {
624 $subpages .= '&lt; ';
626 $subpages .= $getlink;
627 $growinglink .= '/';
632 return $subpages;
635 function nameAndLogin()
637 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
639 $li = $wgLang->specialPage( 'Userlogin' );
640 $lo = $wgLang->specialPage( 'Userlogout' );
642 $s = '';
643 if ( 0 == $wgUser->getID() ) {
644 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
645 $n = $wgIP;
647 $tl = $this->makeKnownLink( $wgLang->getNsText(
648 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
649 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
651 $s .= $n . ' ('.$tl.')';
652 } else {
653 $s .= wfMsg('notloggedin');
656 $rt = $wgTitle->getPrefixedURL();
657 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
658 $q = '';
659 } else { $q = "returnto={$rt}"; }
661 $s .= "\n<br />" . $this->makeKnownLink( $li,
662 wfMsg( 'login' ), $q );
663 } else {
664 $n = $wgUser->getName();
665 $rt = $wgTitle->getPrefixedURL();
666 $tl = $this->makeKnownLink( $wgLang->getNsText(
667 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
668 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
670 $tl = " ({$tl})";
672 $s .= $this->makeKnownLink( $wgLang->getNsText(
673 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
674 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
675 "returnto={$rt}" ) . ' | ' .
676 $this->specialLink( 'preferences' );
678 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
679 wfMsg( 'help' ) );
681 return $s;
684 function getSearchLink() {
685 $searchPage =& Title::makeTitle( NS_SPECIAL, 'Search' );
686 return $searchPage->getLocalURL();
689 function escapeSearchLink() {
690 return htmlspecialchars( $this->getSearchLink() );
693 function searchForm()
695 global $wgRequest;
696 $search = $wgRequest->getText( 'search' );
698 $s = '<form name="search" class="inline" method="post" action="'
699 . $this->escapeSearchLink() . "\">\n"
700 . '<input type="text" name="search" size="19" value="'
701 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
702 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" />&nbsp;'
703 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
705 return $s;
708 function topLinks()
710 global $wgOut;
711 $sep = " |\n";
713 $s = $this->mainPageLink() . $sep
714 . $this->specialLink( 'recentchanges' );
716 if ( $wgOut->isArticleRelated() ) {
717 $s .= $sep . $this->editThisPage()
718 . $sep . $this->historyLink();
720 # Many people don't like this dropdown box
721 #$s .= $sep . $this->specialPagesList();
723 return $s;
726 function bottomLinks()
728 global $wgOut, $wgUser, $wgTitle;
729 $sep = " |\n";
731 $s = '';
732 if ( $wgOut->isArticleRelated() ) {
733 $s .= '<strong>' . $this->editThisPage() . '</strong>';
734 if ( 0 != $wgUser->getID() ) {
735 $s .= $sep . $this->watchThisPage();
737 $s .= $sep . $this->talkLink()
738 . $sep . $this->historyLink()
739 . $sep . $this->whatLinksHere()
740 . $sep . $this->watchPageLinksLink();
742 if ( $wgTitle->getNamespace() == Namespace::getUser()
743 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
746 $id=User::idFromName($wgTitle->getText());
747 $ip=User::isIP($wgTitle->getText());
749 if($id || $ip) { # both anons and non-anons have contri list
750 $s .= $sep . $this->userContribsLink();
752 if ( 0 != $wgUser->getID() ) { # show only to signed in users
753 if($id) { # can only email non-anons
754 $s .= $sep . $this->emailUserLink();
758 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
759 $s .= "\n<br />" . $this->deleteThisPage() .
760 $sep . $this->protectThisPage() .
761 $sep . $this->moveThisPage();
763 $s .= "<br />\n" . $this->otherLanguages();
765 return $s;
768 function pageStats()
770 global $wgOut, $wgLang, $wgArticle, $wgRequest;
771 global $wgDisableCounters;
773 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
774 if ( ! $wgOut->isArticle() ) { return ''; }
775 if ( isset( $oldid ) || isset( $diff ) ) { return ''; }
776 if ( 0 == $wgArticle->getID() ) { return ''; }
778 $s = '';
779 if ( !$wgDisableCounters ) {
780 $count = $wgLang->formatNum( $wgArticle->getCount() );
781 if ( $count ) {
782 $s = wfMsg( 'viewcount', $count );
786 $s .= ' ' . $this->getCredits();
788 return $s . ' ' . $this->getCopyright();
791 function getCredits() {
792 global $wgMaxCredits;
794 $s = '';
796 if (!isset($wgMaxCredits) || $wgMaxCredits == 0) {
797 $s = $this->lastModified();
798 } else {
799 $s = $this->getAuthorCredits();
800 if ($wgMaxCredits > 1) {
801 $s .= ' ' . $this->getContributorCredits();
805 return $s;
808 function getAuthorCredits() {
809 global $wgLang, $wgArticle;
811 $last_author = $wgArticle->getUser();
813 if ($last_author == 0) {
814 $author_credit = wfMsg('anonymous');
815 } else {
816 $real_name = User::whoIsReal($last_author);
817 if (!empty($real_name)) {
818 $author_credit = $real_name;
819 } else {
820 $author_credit = wfMsg('siteuser', User::whoIs($last_author));
824 $timestamp = $wgArticle->getTimestamp();
825 if ( $timestamp ) {
826 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
827 } else {
828 $d = '';
830 return wfMsg('lastmodifiedby', $d, $author_credit);
833 function getContributorCredits() {
835 global $wgArticle, $wgMaxCredits, $wgLang;
837 # don't count last editor
839 $contributors = $wgArticle->getContributors($wgMaxCredits - 1);
841 $real_names = array();
842 $user_names = array();
844 # Sift for real versus user names
846 foreach ($contributors as $user_id => $user_parts) {
847 if ($user_id != 0) {
848 if (!empty($user_parts[1])) {
849 $real_names[$user_id] = $user_parts[1];
850 } else {
851 $user_names[$user_id] = $user_parts[0];
856 $real = $wgLang->listToText(array_values($real_names));
857 $user = $wgLang->listToText(array_values($user_names));
859 if (!empty($user)) {
860 $user = wfMsg('siteusers', $user);
863 if ($contributors[0] && $contributors[0][0] > 0) {
864 $anon = wfMsg('anonymous');
865 } else {
866 $anon = '';
869 $creds = $wgLang->listToText(array($real, $user, $anon));
871 return wfMsg('othercontribs', $creds);
874 function getCopyright() {
875 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
878 $oldid = $wgRequest->getVal( 'oldid' );
879 $diff = $wgRequest->getVal( 'diff' );
881 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
882 $msg = 'history_copyright';
883 } else {
884 $msg = 'copyright';
887 $out = '';
888 if( $wgRightsPage ) {
889 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
890 } elseif( $wgRightsUrl ) {
891 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
892 } else {
893 # Give up now
894 return $out;
896 $out .= wfMsg( $msg, $link );
897 return $out;
900 function getCopyrightIcon() {
901 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
902 $out = '';
903 if( $wgRightsIcon ) {
904 $icon = htmlspecialchars( $wgRightsIcon );
905 if( $wgRightsUrl ) {
906 $url = htmlspecialchars( $wgRightsUrl );
907 $out .= '<a href="'.$url.'">';
909 $text = htmlspecialchars( $wgRightsText );
910 $out .= "<img src=\"$icon\" alt='$text' />";
911 if( $wgRightsUrl ) {
912 $out .= '</a>';
915 return $out;
918 function getPoweredBy() {
919 global $wgStylePath;
920 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
921 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
922 return $img;
925 function lastModified()
927 global $wgLang, $wgArticle;
929 $timestamp = $wgArticle->getTimestamp();
930 if ( $timestamp ) {
931 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
932 $s = ' ' . wfMsg( 'lastmodified', $d );
933 } else {
934 $s = '';
936 return $s;
939 function logoText( $align = '' )
941 if ( '' != $align ) { $a = ' align="'.$align.'"'; }
942 else { $a = ''; }
944 $mp = wfMsg( 'mainpage' );
945 $titleObj = Title::newFromText( $mp );
946 $s = '<a href="' . $titleObj->escapeLocalURL()
947 . '"><img'.$a.' src="'
948 . $this->getLogo() . '" alt="' . "[{$mp}]\" /></a>";
949 return $s;
952 function quickBar()
954 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
955 global $wgDisableUploads, $wgRemoteUploads;
957 $fname = 'Skin::quickBar';
958 wfProfileIn( $fname );
960 $action = $wgRequest->getText( 'action' );
961 $wpPreview = $wgRequest->getBool( 'wpPreview' );
962 $tns=$wgTitle->getNamespace();
964 $s = "\n<div id='quickbar'>";
965 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
967 $sep = "\n<br />";
968 $s .= $this->mainPageLink()
969 . $sep . $this->specialLink( 'recentchanges' )
970 . $sep . $this->specialLink( 'randompage' );
971 if ($wgUser->getID()) {
972 $s.= $sep . $this->specialLink( 'watchlist' ) ;
973 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
974 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
977 // only show watchlist link if logged in
978 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
979 $s .= "\n<br /><hr class='sep' />";
980 $articleExists = $wgTitle->getArticleId();
981 if ( $wgOut->isArticle() || $action =='edit' || $action =='history' || $wpPreview) {
982 if($wgOut->isArticle()) {
983 $s .= '<strong>' . $this->editThisPage() . '</strong>';
984 } else { # backlink to the article in edit or history mode
985 if($articleExists){ # no backlink if no article
986 switch($tns) {
987 case 0:
988 $text = wfMsg('articlepage');
989 break;
990 case 1:
991 $text = wfMsg('viewtalkpage');
992 break;
993 case 2:
994 $text = wfMsg('userpage');
995 break;
996 case 3:
997 $text = wfMsg('viewtalkpage');
998 break;
999 case 4:
1000 $text = wfMsg('wikipediapage');
1001 break;
1002 case 5:
1003 $text = wfMsg('viewtalkpage');
1004 break;
1005 case 6:
1006 $text = wfMsg('imagepage');
1007 break;
1008 case 7:
1009 $text = wfMsg('viewtalkpage');
1010 break;
1011 default:
1012 $text= wfMsg('articlepage');
1015 $link = $wgTitle->getText();
1016 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
1017 $link = $nstext . ':' . $link ;
1020 $s .= $this->makeLink( $link, $text );
1021 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
1022 # we just throw in a "New page" text to tell the user that he's in edit mode,
1023 # and to avoid messing with the separator that is prepended to the next item
1024 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
1030 if( $tns%2 && $action!='edit' && !$wpPreview) {
1031 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit&section=new');
1035 watching could cause problems in edit mode:
1036 if user edits article, then loads "watch this article" in background and then saves
1037 article with "Watch this article" checkbox disabled, the article is transparently
1038 unwatched. Therefore we do not show the "Watch this page" link in edit mode
1040 if ( 0 != $wgUser->getID() && $articleExists) {
1041 if($action!='edit' && $action != 'submit' )
1043 $s .= $sep . $this->watchThisPage();
1045 if ( $wgTitle->userCanEdit() )
1046 $s .= $sep . $this->moveThisPage();
1048 if ( $wgUser->isSysop() and $articleExists ) {
1049 $s .= $sep . $this->deleteThisPage() .
1050 $sep . $this->protectThisPage();
1052 $s .= $sep . $this->talkLink();
1053 if ($articleExists && $action !='history') {
1054 $s .= $sep . $this->historyLink();
1056 $s.=$sep . $this->whatLinksHere();
1058 if($wgOut->isArticleRelated()) {
1059 $s .= $sep . $this->watchPageLinksLink();
1062 if ( Namespace::getUser() == $wgTitle->getNamespace()
1063 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1066 $id=User::idFromName($wgTitle->getText());
1067 $ip=User::isIP($wgTitle->getText());
1069 if($id||$ip) {
1070 $s .= $sep . $this->userContribsLink();
1072 if ( 0 != $wgUser->getID() ) {
1073 if($id) { # can only email real users
1074 $s .= $sep . $this->emailUserLink();
1078 $s .= "\n<br /><hr class='sep' />";
1081 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
1082 $s .= $this->specialLink( 'upload' ) . $sep;
1084 $s .= $this->specialLink( 'specialpages' )
1085 . $sep . $this->bugReportsLink();
1087 global $wgSiteSupportPage;
1088 if( $wgSiteSupportPage ) {
1089 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1090 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1093 $s .= "\n<br /></div>\n";
1094 wfProfileOut( $fname );
1095 return $s;
1098 function specialPagesList()
1100 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1101 require_once('SpecialPage.php');
1102 $a = array();
1103 $pages = SpecialPage::getPages();
1105 foreach ( $pages[''] as $name => $page ) {
1106 $a[$name] = $page->getDescription();
1108 if ( $wgUser->isSysop() )
1110 foreach ( $pages['sysop'] as $name => $page ) {
1111 $a[$name] = $page->getDescription();
1114 if ( $wgUser->isDeveloper() )
1116 foreach ( $pages['developer'] as $name => $page ) {
1117 $a[$name] = $page->getDescription() ;
1120 $go = wfMsg( 'go' );
1121 $sp = wfMsg( 'specialpages' );
1122 $spp = $wgLang->specialPage( 'Specialpages' );
1124 $s = '<form id="specialpages" method="get" class="inline" ' .
1125 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1126 $s .= "<select name=\"wpDropdown\">\n";
1127 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1129 foreach ( $a as $name => $desc ) {
1130 $p = $wgLang->specialPage( $name );
1131 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1133 $s .= "</select>\n";
1134 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1135 $s .= "</form>\n";
1136 return $s;
1139 function mainPageLink()
1141 $mp = wfMsg( 'mainpage' );
1142 $s = $this->makeKnownLink( $mp, $mp );
1143 return $s;
1146 function copyrightLink()
1148 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1149 wfMsg( 'copyrightpagename' ) );
1150 return $s;
1153 function aboutLink()
1155 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1156 wfMsg( 'aboutwikipedia' ) );
1157 return $s;
1161 function disclaimerLink()
1163 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1164 wfMsg( 'disclaimers' ) );
1165 return $s;
1168 function editThisPage()
1170 global $wgOut, $wgTitle, $wgRequest;
1172 $oldid = $wgRequest->getVal( 'oldid' );
1173 $diff = $wgRequest->getVal( 'diff' );
1174 $redirect = $wgRequest->getVal( 'redirect' );
1176 if ( ! $wgOut->isArticleRelated() ) {
1177 $s = wfMsg( 'protectedpage' );
1178 } else {
1179 $n = $wgTitle->getPrefixedText();
1180 if ( $wgTitle->userCanEdit() ) {
1181 $t = wfMsg( 'editthispage' );
1182 } else {
1183 #$t = wfMsg( "protectedpage" );
1184 $t = wfMsg( 'viewsource' );
1186 $oid = $red = '';
1188 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1189 if ( $oldid && ! isset( $diff ) ) {
1190 $oid = "&oldid={$oldid}";
1192 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1194 return $s;
1197 function deleteThisPage()
1199 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1201 $diff = $wgRequest->getVal( 'diff' );
1202 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1203 $n = $wgTitle->getPrefixedText();
1204 $t = wfMsg( 'deletethispage' );
1206 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1207 } else {
1208 $s = '';
1210 return $s;
1213 function protectThisPage()
1215 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1217 $diff = $wgRequest->getVal( 'diff' );
1218 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1219 $n = $wgTitle->getPrefixedText();
1221 if ( $wgTitle->isProtected() ) {
1222 $t = wfMsg( 'unprotectthispage' );
1223 $q = 'action=unprotect';
1224 } else {
1225 $t = wfMsg( 'protectthispage' );
1226 $q = 'action=protect';
1228 $s = $this->makeKnownLink( $n, $t, $q );
1229 } else {
1230 $s = '';
1232 return $s;
1235 function watchThisPage()
1237 global $wgUser, $wgOut, $wgTitle;
1239 if ( $wgOut->isArticleRelated() ) {
1240 $n = $wgTitle->getPrefixedText();
1242 if ( $wgTitle->userIsWatching() ) {
1243 $t = wfMsg( 'unwatchthispage' );
1244 $q = 'action=unwatch';
1245 } else {
1246 $t = wfMsg( 'watchthispage' );
1247 $q = 'action=watch';
1249 $s = $this->makeKnownLink( $n, $t, $q );
1250 } else {
1251 $s = wfMsg( 'notanarticle' );
1253 return $s;
1256 function moveThisPage()
1258 global $wgTitle, $wgLang;
1260 if ( $wgTitle->userCanEdit() ) {
1261 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1262 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1263 } // no message if page is protected - would be redundant
1264 return $s;
1267 function historyLink()
1269 global $wgTitle;
1271 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1272 wfMsg( 'history' ), 'action=history' );
1273 return $s;
1276 function whatLinksHere()
1278 global $wgTitle, $wgLang;
1280 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1281 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1282 return $s;
1285 function userContribsLink()
1287 global $wgTitle, $wgLang;
1289 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1290 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1291 return $s;
1294 function emailUserLink()
1296 global $wgTitle, $wgLang;
1298 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1299 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1300 return $s;
1303 function watchPageLinksLink()
1305 global $wgOut, $wgTitle, $wgLang;
1307 if ( ! $wgOut->isArticleRelated() ) {
1308 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1309 } else {
1310 $s = $this->makeKnownLink( $wgLang->specialPage(
1311 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1312 'target=' . $wgTitle->getPrefixedURL() );
1314 return $s;
1317 function otherLanguages()
1319 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1321 $a = $wgOut->getLanguageLinks();
1322 if ( 0 == count( $a ) ) {
1323 if ( !$wgUseNewInterlanguage ) return '';
1324 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1325 if ( $ns != 0 AND $ns != 1 ) return '' ;
1326 $pn = 'Intl' ;
1327 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1328 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1329 wfMsg( 'intl' ) , $x );
1332 if ( !$wgUseNewInterlanguage ) {
1333 $s = wfMsg( 'otherlanguages' ) . ': ';
1334 } else {
1335 global $wgLanguageCode ;
1336 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1337 $x .= '&xl='.$wgLanguageCode ;
1338 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1339 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1342 $s = wfMsg( 'otherlanguages' ) . ': ';
1343 $first = true;
1344 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1345 foreach( $a as $l ) {
1346 if ( ! $first ) { $s .= ' | '; }
1347 $first = false;
1349 $nt = Title::newFromText( $l );
1350 $url = $nt->getFullURL();
1351 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1353 if ( '' == $text ) { $text = $l; }
1354 $style = $this->getExternalLinkAttributes( $l, $text );
1355 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1357 if($wgLang->isRTL()) $s .= '</span>';
1358 return $s;
1361 function bugReportsLink()
1363 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1364 wfMsg( 'bugreports' ) );
1365 return $s;
1368 function dateLink()
1370 global $wgLinkCache;
1371 $t1 = Title::newFromText( gmdate( 'F j' ) );
1372 $t2 = Title::newFromText( gmdate( 'Y' ) );
1374 $wgLinkCache->suspend();
1375 $id = $t1->getArticleID();
1376 $wgLinkCache->resume();
1378 if ( 0 == $id ) {
1379 $s = $this->makeBrokenLink( $t1->getText() );
1380 } else {
1381 $s = $this->makeKnownLink( $t1->getText() );
1383 $s .= ', ';
1385 $wgLinkCache->suspend();
1386 $id = $t2->getArticleID();
1387 $wgLinkCache->resume();
1389 if ( 0 == $id ) {
1390 $s .= $this->makeBrokenLink( $t2->getText() );
1391 } else {
1392 $s .= $this->makeKnownLink( $t2->getText() );
1394 return $s;
1397 function talkLink()
1399 global $wgLang, $wgTitle, $wgLinkCache;
1401 $tns = $wgTitle->getNamespace();
1402 if ( -1 == $tns ) { return ''; }
1404 $pn = $wgTitle->getText();
1405 $tp = wfMsg( 'talkpage' );
1406 if ( Namespace::isTalk( $tns ) ) {
1407 $lns = Namespace::getSubject( $tns );
1408 switch($tns) {
1409 case 1:
1410 $text = wfMsg('articlepage');
1411 break;
1412 case 3:
1413 $text = wfMsg('userpage');
1414 break;
1415 case 5:
1416 $text = wfMsg('wikipediapage');
1417 break;
1418 case 7:
1419 $text = wfMsg('imagepage');
1420 break;
1421 default:
1422 $text= wfMsg('articlepage');
1424 } else {
1426 $lns = Namespace::getTalk( $tns );
1427 $text=$tp;
1429 $n = $wgLang->getNsText( $lns );
1430 if ( '' == $n ) { $link = $pn; }
1431 else { $link = $n.':'.$pn; }
1433 $wgLinkCache->suspend();
1434 $s = $this->makeLink( $link, $text );
1435 $wgLinkCache->resume();
1437 return $s;
1440 function commentLink()
1442 global $wgLang, $wgTitle, $wgLinkCache;
1444 $tns = $wgTitle->getNamespace();
1445 if ( -1 == $tns ) { return ''; }
1447 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1449 # assert Namespace::isTalk( $lns )
1451 $n = $wgLang->getNsText( $lns );
1452 $pn = $wgTitle->getText();
1454 $link = $n.':'.$pn;
1456 $wgLinkCache->suspend();
1457 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit&section=new');
1458 $wgLinkCache->resume();
1460 return $s;
1463 # After all the page content is transformed into HTML, it makes
1464 # a final pass through here for things like table backgrounds.
1466 function transformContent( $text )
1468 return $text;
1471 # Note: This function MUST call getArticleID() on the link,
1472 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1474 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1475 wfProfileIn( 'Skin::makeLink' );
1476 $nt = Title::newFromText( $title );
1477 if ($nt) {
1478 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1479 } else {
1480 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1481 $result = $text == "" ? $title : $text;
1484 wfProfileOut( 'Skin::makeLink' );
1485 return $result;
1488 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1489 $nt = Title::newFromText( $title );
1490 if ($nt) {
1491 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1492 } else {
1493 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1494 return $text == '' ? $title : $text;
1498 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1499 $nt = Title::newFromText( $title );
1500 if ($nt) {
1501 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1502 } else {
1503 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1504 return $text == '' ? $title : $text;
1508 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1509 $nt = Title::newFromText( $title );
1510 if ($nt) {
1511 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1512 } else {
1513 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1514 return $text == '' ? $title : $text;
1518 # Pass a title object, not a title string
1519 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1521 global $wgOut, $wgUser;
1522 if ( $nt->isExternal() ) {
1523 $u = $nt->getFullURL();
1524 $link = $nt->getPrefixedURL();
1525 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1526 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1528 $inside = '';
1529 if ( '' != $trail ) {
1530 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1531 $inside = $m[1];
1532 $trail = $m[2];
1535 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1536 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1537 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1538 } elseif ( ( -1 == $nt->getNamespace() ) ||
1539 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1540 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1541 } else {
1542 $aid = $nt->getArticleID() ;
1543 if ( 0 == $aid ) {
1544 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1545 } else {
1546 $threshold = $wgUser->getOption('stubthreshold') ;
1547 if ( $threshold > 0 ) {
1548 $res = wfQuery ( "SELECT LENGTH(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ ) ;
1550 if ( wfNumRows( $res ) > 0 ) {
1551 $s = wfFetchObject( $res );
1552 $size = $s->x;
1553 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1554 $size = $threshold*2 ; # Really big
1556 wfFreeResult( $res );
1557 } else {
1558 $size = $threshold*2 ; # Really big
1560 } else {
1561 $size = 1 ;
1563 if ( $size < $threshold ) {
1564 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1565 } else {
1566 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1570 return $retVal;
1573 # Pass a title object, not a title string
1574 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1576 global $wgOut, $wgTitle, $wgInputEncoding;
1578 $fname = 'Skin::makeKnownLinkObj';
1579 wfProfileIn( $fname );
1581 if ( !is_object( $nt ) ) {
1582 return $text;
1584 $link = $nt->getPrefixedURL();
1586 if ( '' == $link ) {
1587 $u = '';
1588 if ( '' == $text ) {
1589 $text = htmlspecialchars( $nt->getFragment() );
1591 } else {
1592 $u = $nt->escapeLocalURL( $query );
1594 if ( '' != $nt->getFragment() ) {
1595 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT, $wgInputEncoding ) );
1596 $replacearray = array(
1597 '%3A' => ':',
1598 '%' => '.'
1600 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1602 if ( '' == $text ) {
1603 $text = htmlspecialchars( $nt->getPrefixedText() );
1605 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1607 $inside = '';
1608 if ( '' != $trail ) {
1609 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1610 $inside = $m[1];
1611 $trail = $m[2];
1614 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1615 wfProfileOut( $fname );
1616 return $r;
1619 # Pass a title object, not a title string
1620 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1622 global $wgOut, $wgUser;
1624 $fname = 'Skin::makeBrokenLinkObj';
1625 wfProfileIn( $fname );
1627 if ( '' == $query ) {
1628 $q = 'action=edit';
1629 } else {
1630 $q = 'action=edit&'.$query;
1632 $u = $nt->escapeLocalURL( $q );
1634 if ( '' == $text ) {
1635 $text = htmlspecialchars( $nt->getPrefixedText() );
1637 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1639 $inside = '';
1640 if ( '' != $trail ) {
1641 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1642 $inside = $m[1];
1643 $trail = $m[2];
1646 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1647 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1648 } else {
1649 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1652 wfProfileOut( $fname );
1653 return $s;
1656 # Pass a title object, not a title string
1657 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1659 global $wgOut, $wgUser;
1661 $link = $nt->getPrefixedURL();
1663 $u = $nt->escapeLocalURL( $query );
1665 if ( '' == $text ) {
1666 $text = htmlspecialchars( $nt->getPrefixedText() );
1668 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1670 $inside = '';
1671 if ( '' != $trail ) {
1672 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1673 $inside = $m[1];
1674 $trail = $m[2];
1677 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1678 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1679 } else {
1680 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1682 return $s;
1685 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1687 $u = $nt->escapeLocalURL( $query );
1688 if ( '' == $text ) {
1689 $text = htmlspecialchars( $nt->getPrefixedText() );
1691 $inside = '';
1692 if ( '' != $trail ) {
1693 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1694 $inside = $m[1];
1695 $trail = $m[2];
1698 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1701 /* these are used extensively in SkinPHPTal, but also some other places */
1702 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1703 $title = Title::makeTitle( NS_SPECIAL, $name );
1704 $this->checkTitle($title, $name);
1705 return $title->getLocalURL( $urlaction );
1707 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1708 $title = Title::newFromText( $name );
1709 $title = $title->getTalkPage();
1710 $this->checkTitle($title, $name);
1711 return $title->getLocalURL( $urlaction );
1713 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1714 $title = Title::newFromText( $name );
1715 $title= $title->getSubjectPage();
1716 $this->checkTitle($title, $name);
1717 return $title->getLocalURL( $urlaction );
1719 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1720 $title = Title::newFromText( wfMsg($name) );
1721 $this->checkTitle($title, $name);
1722 return $title->getLocalURL( $urlaction );
1724 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1725 $title = Title::newFromText( $name );
1726 $this->checkTitle($title, $name);
1727 return $title->getLocalURL( $urlaction );
1729 # this can be passed the NS number as defined in Language.php
1730 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1731 $title = Title::makeTitle( $namespace, $name );
1732 $this->checkTitle($title, $name);
1733 return $title->getLocalURL( $urlaction );
1736 /* these return an array with the 'href' and boolean 'exists' */
1737 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1738 $title = Title::newFromText( $name );
1739 $this->checkTitle($title, $name);
1740 return array(
1741 'href' => $title->getLocalURL( $urlaction ),
1742 'exists' => $title->getArticleID() != 0?true:false
1745 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1746 $title = Title::newFromText( $name );
1747 $title = $title->getTalkPage();
1748 $this->checkTitle($title, $name);
1749 return array(
1750 'href' => $title->getLocalURL( $urlaction ),
1751 'exists' => $title->getArticleID() != 0?true:false
1754 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1755 $title = Title::newFromText( $name );
1756 $title= $title->getSubjectPage();
1757 $this->checkTitle($title, $name);
1758 return array(
1759 'href' => $title->getLocalURL( $urlaction ),
1760 'exists' => $title->getArticleID() != 0?true:false
1763 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1764 $title = Title::newFromText( wfMsg($name) );
1765 $this->checkTitle($title, $name);
1766 return array(
1767 'href' => $title->getLocalURL( $urlaction ),
1768 'exists' => $title->getArticleID() != 0?true:false
1772 # make sure we have some title to operate on
1773 /*static*/ function checkTitle ( &$title, &$name ) {
1774 if(!is_object($title)) {
1775 $title = Title::newFromText( $name );
1776 if(!is_object($title)) {
1777 $title = Title::newFromText( '<error: link target missing>' );
1782 function fnamePart( $url )
1784 $basename = strrchr( $url, '/' );
1785 if ( false === $basename ) { $basename = $url; }
1786 else { $basename = substr( $basename, 1 ); }
1787 return wfEscapeHTML( $basename );
1790 function makeImage( $url, $alt = '' )
1792 global $wgOut;
1794 if ( '' == $alt ) { $alt = $this->fnamePart( $url ); }
1795 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1796 return $s;
1799 function makeImageLink( $name, $url, $alt = '' ) {
1800 $nt = Title::makeTitle( Namespace::getImage(), $name );
1801 return $this->makeImageLinkObj( $nt, $alt );
1804 function makeImageLinkObj( $nt, $alt = '' ) {
1805 global $wgLang, $wgUseImageResize;
1806 $img = Image::newFromTitle( $nt );
1807 $url = $img->getURL();
1809 $align = '';
1810 $prefix = $postfix = '';
1812 if ( $wgUseImageResize ) {
1813 # Check if the alt text is of the form "options|alt text"
1814 # Options are:
1815 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1816 # * left no resizing, just left align. label is used for alt= only
1817 # * right same, but right aligned
1818 # * none same, but not aligned
1819 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1820 # * center center the image
1821 # * framed Keep original image size, no magnify-button.
1823 $part = explode( '|', $alt);
1825 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1826 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1827 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1828 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1829 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1830 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1831 $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
1832 $alt = $part[count($part)-1];
1834 $height = $framed = $thumb = false;
1836 foreach( $part as $key => $val ) {
1837 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1838 $thumb=true;
1839 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1840 # remember to set an alignment, don't render immediately
1841 $align = 'right';
1842 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1843 # remember to set an alignment, don't render immediately
1844 $align = 'left';
1845 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1846 # remember to set an alignment, don't render immediately
1847 $align = 'center';
1848 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1849 # remember to set an alignment, don't render immediately
1850 $align = 'none';
1851 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1852 # $match is the image width in pixels
1853 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1854 $width = intval( $m[1] );
1855 $height = intval( $m[2] );
1856 } else {
1857 $width = intval($match);
1859 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1860 $framed=true;
1863 if ( 'center' == $align )
1865 $prefix = '<span style="text-align: center">';
1866 $postfix = '</span>';
1867 $align = 'none';
1870 if ( $thumb || $framed ) {
1872 # Create a thumbnail. Alignment depends on language
1873 # writing direction, # right aligned for left-to-right-
1874 # languages ("Western languages"), left-aligned
1875 # for right-to-left-languages ("Semitic languages")
1877 # If thumbnail width has not been provided, it is set
1878 # here to 180 pixels
1879 if ( $align == '' ) {
1880 $align = $wgLang->isRTL() ? 'left' : 'right';
1882 if ( ! isset($width) ) {
1883 $width = 180;
1885 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed ).$postfix;
1887 } elseif ( isset($width) ) {
1889 # Create a resized image, without the additional thumbnail
1890 # features
1892 if ( ( ! $height === false )
1893 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1894 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1895 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1896 $width = $img->getWidth() * $height / $img->getHeight();
1898 $url = $img->createThumb( $width );
1900 } # endif $wgUseImageResize
1902 if ( empty( $alt ) ) {
1903 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1905 $alt = htmlspecialchars( $alt );
1907 $u = $nt->escapeLocalURL();
1908 if ( $url == '' )
1910 $s = str_replace( "$1", $img->getName(), wfMsg('missingimage') );
1911 $s .= "<br>{$alt}<br>{$url}<br>\n";
1912 } else {
1913 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1914 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1916 if ( '' != $align ) {
1917 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1919 return str_replace("\n", ' ',$prefix.$s.$postfix);
1923 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false ) {
1924 global $wgStylePath, $wgLang;
1925 # $image = Title::makeTitle( Namespace::getImage(), $name );
1926 $url = $img->getURL();
1928 #$label = htmlspecialchars( $label );
1929 $alt = preg_replace( '/<[^>]*>/', '', $label);
1930 $alt = htmlspecialchars( $alt );
1932 if ( $img->exists() )
1934 $width = $img->getWidth();
1935 $height = $img->getHeight();
1936 } else {
1937 $width = $height = 200;
1939 if ( $framed )
1941 // Use image dimensions, don't scale
1942 $boxwidth = $width;
1943 $oboxwidth = $boxwidth + 2;
1944 $boxheight = $height;
1945 $thumbUrl = $url;
1946 } else {
1947 $h = intval( $height/($width/$boxwidth) );
1948 $oboxwidth = $boxwidth + 2;
1949 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1951 $boxwidth *= $boxheight/$h;
1952 } else {
1953 $boxheight = $h;
1955 $thumbUrl = $img->createThumb( $boxwidth );
1958 $u = $img->getEscapeLocalURL();
1960 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1961 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1962 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1964 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1965 if ( $thumbUrl == '' ) {
1966 $s .= str_replace( "$1", $img->getName(), wfMsg('missingimage') );
1967 $zoomicon = '';
1968 } else {
1969 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1970 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1971 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1972 if ( $framed ) {
1973 $zoomicon="";
1974 } else {
1975 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1976 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1977 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1978 'width="15" height="11" alt="'.$more.'" /></a></div>';
1981 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1982 return str_replace("\n", ' ', $s);
1985 function makeMediaLink( $name, $url, $alt = "" ) {
1986 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1987 return $this->makeMediaLinkObj( $nt, $alt );
1990 function makeMediaLinkObj( $nt, $alt = "" )
1992 if ( ! isset( $nt ) )
1994 ### HOTFIX. Instead of breaking, return empry string.
1995 $s = $alt;
1996 } else {
1997 $name = $nt->getDBKey();
1998 $url = Image::wfImageUrl( $name );
1999 if ( empty( $alt ) ) {
2000 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2003 $u = htmlspecialchars( $url );
2004 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2006 return $s;
2009 function specialLink( $name, $key = "" )
2011 global $wgLang;
2013 if ( '' == $key ) { $key = strtolower( $name ); }
2014 $pn = $wgLang->ucfirst( $name );
2015 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2016 wfMsg( $key ) );
2019 function makeExternalLink( $url, $text, $escape = true ) {
2020 $style = $this->getExternalLinkAttributes( $url, $text );
2021 $url = htmlspecialchars( $url );
2022 if( $escape ) {
2023 $text = htmlspecialchars( $text );
2025 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2028 # Called by history lists and recent changes
2031 # Returns text for the start of the tabular part of RC
2032 function beginRecentChangesList()
2034 $this->rc_cache = array() ;
2035 $this->rcMoveIndex = 0;
2036 $this->rcCacheIndex = 0 ;
2037 $this->lastdate = '';
2038 $this->rclistOpen = false;
2039 return '';
2042 function beginImageHistoryList()
2044 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2045 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2046 return $s;
2049 # Returns text for the end of RC
2050 # If enhanced RC is in use, returns pretty much all the text
2051 function endRecentChangesList()
2053 $s = $this->recentChangesBlock() ;
2054 if( $this->rclistOpen ) {
2055 $s .= "</ul>\n";
2057 return $s;
2060 # Enhanced RC ungrouped line
2061 function recentChangesBlockLine ( $rcObj )
2063 global $wgStylePath, $wgLang ;
2065 # Get rc_xxxx variables
2066 extract( $rcObj->mAttribs ) ;
2067 $curIdEq = 'curid='.$rc_cur_id;
2069 # Spacer image
2070 $r = '' ;
2072 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2073 $r .= '<tt>' ;
2075 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2076 $r .= '&nbsp;&nbsp;';
2077 } else {
2078 # M & N (minor & new)
2079 $M = wfMsg( 'minoreditletter' );
2080 $N = wfMsg( 'newpageletter' );
2082 if ( $rc_type == RC_NEW ) {
2083 $r .= $N ;
2084 } else {
2085 $r .= '&nbsp;' ;
2087 if ( $rc_minor ) {
2088 $r .= $M ;
2089 } else {
2090 $r .= '&nbsp;' ;
2094 # Timestamp
2095 $r .= ' '.$rcObj->timestamp.' ' ;
2096 $r .= '</tt>' ;
2098 # Article link
2099 $link = $rcObj->link ;
2100 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2101 $r .= $link ;
2103 # Diff
2104 $r .= ' (' ;
2105 $r .= $rcObj->difflink ;
2106 $r .= '; ' ;
2108 # Hist
2109 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2111 # User/talk
2112 $r .= ') . . '.$rcObj->userlink ;
2113 $r .= $rcObj->usertalklink ;
2115 # Comment
2116 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2117 $rc_comment=$this->formatComment($rc_comment);
2118 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2121 $r .= "<br />\n" ;
2122 return $r ;
2125 # Enhanced RC group
2126 function recentChangesBlockGroup ( $block )
2128 global $wgStylePath, $wgLang ;
2130 $r = '' ;
2131 $M = wfMsg( 'minoreditletter' );
2132 $N = wfMsg( 'newpageletter' );
2134 # Collate list of users
2135 $isnew = false ;
2136 $userlinks = array () ;
2137 foreach ( $block AS $rcObj ) {
2138 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2139 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2140 $u = $rcObj->userlink ;
2141 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2142 $userlinks[$u]++ ;
2145 # Sort the list and convert to text
2146 krsort ( $userlinks ) ;
2147 asort ( $userlinks ) ;
2148 $users = array () ;
2149 foreach ( $userlinks as $userlink => $count) {
2150 $text = $userlink ;
2151 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2152 array_push ( $users , $text ) ;
2154 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2156 # Arrow
2157 $rci = 'RCI'.$this->rcCacheIndex ;
2158 $rcl = 'RCL'.$this->rcCacheIndex ;
2159 $rcm = 'RCM'.$this->rcCacheIndex ;
2160 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2161 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2162 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2163 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2164 $r .= $tl ;
2166 # Main line
2167 # M/N
2168 $r .= '<tt>' ;
2169 if ( $isnew ) $r .= $N ;
2170 else $r .= '&nbsp;' ;
2171 $r .= '&nbsp;' ; # Minor
2173 # Timestamp
2174 $r .= ' '.$block[0]->timestamp.' ' ;
2175 $r .= '</tt>' ;
2177 # Article link
2178 $link = $block[0]->link ;
2179 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2180 $r .= $link ;
2182 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2183 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2184 # Changes
2185 $r .= ' ('.count($block).' ' ;
2186 if ( $isnew ) $r .= wfMsg('changes');
2187 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2188 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2189 $r .= '; ' ;
2191 # History
2192 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2193 $r .= ')' ;
2196 $r .= $users ;
2197 $r .= "<br />\n" ;
2199 # Sub-entries
2200 $r .= '<div id="'.$rci.'" style="display:none">' ;
2201 foreach ( $block AS $rcObj ) {
2202 # Get rc_xxxx variables
2203 extract( $rcObj->mAttribs );
2205 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2206 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2207 if ( $rc_new ) $r .= $N ;
2208 else $r .= '&nbsp;' ;
2209 if ( $rc_minor ) $r .= $M ;
2210 else $r .= '&nbsp;' ;
2211 $r .= '</tt>' ;
2213 $o = '' ;
2214 if ( $rc_last_oldid != 0 ) {
2215 $o = 'oldid='.$rc_last_oldid ;
2217 if ( $rc_type == RC_LOG ) {
2218 $link = $rcObj->timestamp ;
2219 } else {
2220 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2222 $link = '<tt>'.$link.'</tt>' ;
2224 $r .= $link ;
2225 $r .= ' (' ;
2226 $r .= $rcObj->curlink ;
2227 $r .= '; ' ;
2228 $r .= $rcObj->lastlink ;
2229 $r .= ') . . '.$rcObj->userlink ;
2230 $r .= $rcObj->usertalklink ;
2231 if ( $rc_comment != '' ) {
2232 $rc_comment=$this->formatComment($rc_comment);
2233 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2235 $r .= "<br />\n" ;
2237 $r .= "</div>\n" ;
2239 $this->rcCacheIndex++ ;
2240 return $r ;
2243 # If enhanced RC is in use, this function takes the previously cached
2244 # RC lines, arranges them, and outputs the HTML
2245 function recentChangesBlock ()
2247 global $wgStylePath ;
2248 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2249 $blockOut = '';
2250 foreach ( $this->rc_cache AS $secureName => $block ) {
2251 if ( count ( $block ) < 2 ) {
2252 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2253 } else {
2254 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2258 return '<div>'.$blockOut.'</div>' ;
2261 # Called in a loop over all displayed RC entries
2262 # Either returns the line, or caches it for later use
2263 function recentChangesLine( &$rc, $watched = false )
2265 global $wgUser ;
2266 $usenew = $wgUser->getOption( 'usenewrc' );
2267 if ( $usenew )
2268 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2269 else
2270 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2271 return $line ;
2274 function recentChangesLineOld( &$rc, $watched = false )
2276 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2278 # Extract DB fields into local scope
2279 extract( $rc->mAttribs );
2280 $curIdEq = 'curid=' . $rc_cur_id;
2282 # Make date header if necessary
2283 $date = $wgLang->date( $rc_timestamp, true);
2284 $s = '';
2285 if ( $date != $this->lastdate ) {
2286 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2287 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2288 $this->lastdate = $date;
2289 $this->rclistOpen = true;
2291 $s .= '<li> ';
2293 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2294 # Diff
2295 $s .= '(' . wfMsg( 'diff' ) . ') (';
2296 # Hist
2297 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2298 ') . . ';
2300 # "[[x]] moved to [[y]]"
2301 if ( $rc_type == RC_MOVE ) {
2302 $msg = '1movedto2';
2303 } else {
2304 $msg = '1movedto2_redir';
2306 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2307 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2308 } else {
2309 # Diff link
2310 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2311 $diffLink = wfMsg( 'diff' );
2312 } else {
2313 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2314 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid ,'' ,'' , ' tabindex="'.$rc->counter.'"');
2316 $s .= '('.$diffLink.') (';
2318 # History link
2319 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2320 $s .= ') . . ';
2322 # M and N (minor and new)
2323 $M = wfMsg( 'minoreditletter' );
2324 $N = wfMsg( 'newpageletter' );
2325 if ( $rc_minor ) { $s .= ' <strong>'.$M.'</strong>'; }
2326 if ( $rc_type == RC_NEW ) { $s .= '<strong>'.$N.'</strong>'; }
2328 # Article link
2329 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2331 if ( $watched ) {
2332 $articleLink = '<strong>'.$articleLink.'</strong>';
2334 $s .= ' '.$articleLink;
2338 # Timestamp
2339 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2341 # User link (or contributions for unregistered users)
2342 if ( 0 == $rc_user ) {
2343 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2344 $rc_user_text, 'target=' . $rc_user_text );
2345 } else {
2346 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2348 $s .= $userLink;
2350 # User talk link
2351 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2352 global $wgDisableAnonTalk;
2353 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2354 $userTalkLink = '';
2355 } else {
2356 $utns=$wgLang->getNsText(NS_USER_TALK);
2357 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2359 # Block link
2360 $blockLink='';
2361 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2362 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2363 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2366 if($blockLink) {
2367 if($userTalkLink) $userTalkLink .= ' | ';
2368 $userTalkLink .= $blockLink;
2370 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2372 # Add comment
2373 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2374 $rc_comment=$this->formatComment($rc_comment);
2375 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2377 $s .= "</li>\n";
2379 return $s;
2382 # function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
2383 function recentChangesLineNew( &$baseRC, $watched = false )
2385 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2387 # Create a specialised object
2388 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2390 # Extract fields from DB into the function scope (rc_xxxx variables)
2391 extract( $rc->mAttribs );
2392 $curIdEq = 'curid=' . $rc_cur_id;
2394 # If it's a new day, add the headline and flush the cache
2395 $date = $wgLang->date( $rc_timestamp, true);
2396 $ret = '' ;
2397 if ( $date != $this->lastdate ) {
2398 # Process current cache
2399 $ret = $this->recentChangesBlock () ;
2400 $this->rc_cache = array() ;
2401 $ret .= "<h4>{$date}</h4>\n";
2402 $this->lastdate = $date;
2405 # Make article link
2406 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2407 if ( $rc_type == RC_MOVE ) {
2408 $msg = "1movedto2";
2409 } else {
2410 $msg = "1movedto2_redir";
2412 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2413 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2414 } else {
2415 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2418 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2419 $rc->watched = $watched ;
2420 $rc->link = $clink ;
2421 $rc->timestamp = $time;
2423 # Make "cur" and "diff" links
2424 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2425 $curLink = wfMsg( 'cur' );
2426 $diffLink = wfMsg( 'diff' );
2427 } else {
2428 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2429 $aprops = ' tabindex="'.$baseRC->counter.'"';
2430 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2431 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2434 # Make "last" link
2435 $titleObj = $rc->getTitle();
2436 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2437 $lastLink = wfMsg( 'last' );
2438 } else {
2439 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2440 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2443 # Make user link (or user contributions for unregistered users)
2444 if ( 0 == $rc_user ) {
2445 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2446 $rc_user_text, 'target=' . $rc_user_text );
2447 } else {
2448 $userLink = $this->makeLink( $wgLang->getNsText(
2449 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2452 $rc->userlink = $userLink ;
2453 $rc->lastlink = $lastLink ;
2454 $rc->curlink = $curLink ;
2455 $rc->difflink = $diffLink;
2458 # Make user talk link
2459 $utns=$wgLang->getNsText(NS_USER_TALK);
2460 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2461 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2463 global $wgDisableAnonTalk;
2464 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2465 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2466 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2467 if( $wgDisableAnonTalk )
2468 $rc->usertalklink = ' ('.$blockLink.')';
2469 else
2470 $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
2471 } else {
2472 if( $wgDisableAnonTalk && ($rc_user == 0) )
2473 $rc->usertalklink = '';
2474 else
2475 $rc->usertalklink = ' ('.$userTalkLink.')';
2478 # Put accumulated information into the cache, for later display
2479 # Page moves go on their own line
2480 $title = $rc->getTitle();
2481 $secureName = $title->getPrefixedDBkey();
2482 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2483 # Use an @ character to prevent collision with page names
2484 $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
2485 } else {
2486 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2487 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2489 return $ret;
2492 function endImageHistoryList()
2494 $s = "</ul>\n";
2495 return $s;
2498 /* This function is called by all recent changes variants, by the page history,
2499 and by the user contributions list. It is responsible for formatting edit
2500 comments. It escapes any HTML in the comment, but adds some CSS to format
2501 auto-generated comments (from section editing) and formats [[wikilinks]].
2502 Main author: Erik Möller (moeller@scireview.de)
2504 function formatComment($comment)
2506 global $wgLang;
2507 $comment=wfEscapeHTML($comment);
2509 # The pattern for autogen comments is / * foo * /, which makes for
2510 # some nasty regex.
2511 # We look for all comments, match any text before and after the comment,
2512 # add a separator where needed and format the comment itself with CSS
2513 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2514 $pre=$match[1];
2515 $auto=$match[2];
2516 $post=$match[3];
2517 $sep='-';
2518 if($pre) { $auto = $sep.' '.$auto; }
2519 if($post) { $auto .= ' '.$sep; }
2520 $auto='<span class="autocomment">'.$auto.'</span>';
2521 $comment=$pre.$auto.$post;
2524 # format regular and media links - all other wiki formatting
2525 # is ignored
2526 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\]/',$comment,$match)) {
2528 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2529 $func='makeLink';
2530 if(preg_match('/^'.$medians.'/i',$match[1])) {
2531 $func='makeMediaLink';
2533 # Handle link renaming [[foo|text]] will show link as "text"
2534 if(isset($match[3]) ) {
2535 $comment=
2536 preg_replace('/\[\[(.*?)\]\]/',
2537 $this->$func($match[1],$match[3]),$comment,1);
2538 } else {
2539 $comment=
2540 preg_replace('/\[\[(.*?)\]\]/',
2541 $this->$func($match[1],$match[1]),$comment,1);
2545 return $comment;
2549 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2551 global $wgUser, $wgLang, $wgTitle;
2553 $datetime = $wgLang->timeanddate( $timestamp, true );
2554 $del = wfMsg( 'deleteimg' );
2555 $cur = wfMsg( 'cur' );
2557 if ( $iscur ) {
2558 $url = Image::wfImageUrl( $img );
2559 $rlink = $cur;
2560 if ( $wgUser->isSysop() ) {
2561 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2562 '&action=delete' );
2563 $style = $this->getInternalLinkAttributes( $link, $del );
2565 $dlink = '<a href="'.$link.'"'.$style.'>'.$del.'</a>';
2566 } else {
2567 $dlink = $del;
2569 } else {
2570 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
2571 if( $wgUser->getID() != 0 ) {
2572 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2573 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2574 urlencode( $img ) );
2575 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2576 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2577 } else {
2578 # Having live active links for non-logged in users
2579 # means that bots and spiders crawling our site can
2580 # inadvertently change content. Baaaad idea.
2581 $rlink = wfMsg( 'revertimg' );
2582 $dlink = $del;
2585 if ( 0 == $user ) {
2586 $userlink = $usertext;
2587 } else {
2588 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2589 ':'.$usertext, $usertext );
2591 $nbytes = wfMsg( 'nbytes', $size );
2592 $style = $this->getInternalLinkAttributes( $url, $datetime );
2594 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2595 . " . . {$userlink} ({$nbytes})";
2597 if ( '' != $description && '*' != $description ) {
2598 $sk=$wgUser->getSkin();
2599 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2601 $s .= "</li>\n";
2602 return $s;
2605 function tocIndent($level) {
2606 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2609 function tocUnindent($level) {
2610 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2613 # parameter level defines if we are on an indentation level
2614 function tocLine( $anchor, $tocline, $level ) {
2615 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2616 if($level) {
2617 return $link."\n";
2618 } else {
2619 return '<div class="tocline">'.$link."</div>\n";
2624 function tocTable($toc) {
2625 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2626 # try min-width & co when somebody gets a chance
2627 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2628 return
2629 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2630 '<b>'.wfMsg('toc').'</b>' .
2631 $hideline .
2632 '</td></tr><tr id="tocinside"><td>'."\n".
2633 $toc."</td></tr></table>\n";
2636 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2637 function editSectionScript( $section, $head ) {
2638 global $wgTitle, $wgRequest;
2639 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2640 return $head;
2642 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2643 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2646 function editSectionLink( $section ) {
2647 global $wgRequest;
2648 global $wgTitle, $wgUser, $wgLang;
2650 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2651 # Section edit links would be out of sync on an old page.
2652 # But, if we're diffing to the current page, they'll be
2653 # correct.
2654 return '';
2657 $editurl = '&section='.$section;
2658 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2660 if( $wgLang->isRTL() ) {
2661 $farside = 'left';
2662 $nearside = 'right';
2663 } else {
2664 $farside = 'right';
2665 $nearside = 'left';
2667 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2671 // This function is called by EditPage.php and shows a bulletin board style
2672 // toolbar for common editing functions. It can be disabled in the user preferences.
2673 // The necsesary JavaScript code can be found in style/wikibits.js.
2674 function getEditToolbar() {
2675 global $wgStylePath, $wgLang, $wgMimeType;
2677 // toolarray an array of arrays which each include the filename of
2678 // the button image (without path), the opening tag, the closing tag,
2679 // and optionally a sample text that is inserted between the two when no
2680 // selection is highlighted.
2681 // The tip text is shown when the user moves the mouse over the button.
2683 // Already here are accesskeys (key), which are not used yet until someone
2684 // can figure out a way to make them work in IE. However, we should make
2685 // sure these keys are not defined on the edit page.
2686 $toolarray=array(
2687 array( 'image'=>'button_bold.png',
2688 'open'=>"\'\'\'",
2689 'close'=>"\'\'\'",
2690 'sample'=>wfMsg('bold_sample'),
2691 'tip'=>wfMsg('bold_tip'),
2692 'key'=>'B'
2694 array( "image"=>"button_italic.png",
2695 "open"=>"\'\'",
2696 "close"=>"\'\'",
2697 "sample"=>wfMsg("italic_sample"),
2698 "tip"=>wfMsg("italic_tip"),
2699 "key"=>"I"
2701 array( "image"=>"button_link.png",
2702 "open"=>"[[",
2703 "close"=>"]]",
2704 "sample"=>wfMsg("link_sample"),
2705 "tip"=>wfMsg("link_tip"),
2706 "key"=>"L"
2708 array( "image"=>"button_extlink.png",
2709 "open"=>"[",
2710 "close"=>"]",
2711 "sample"=>wfMsg("extlink_sample"),
2712 "tip"=>wfMsg("extlink_tip"),
2713 "key"=>"X"
2715 array( "image"=>"button_headline.png",
2716 "open"=>"\\n== ",
2717 "close"=>" ==\\n",
2718 "sample"=>wfMsg("headline_sample"),
2719 "tip"=>wfMsg("headline_tip"),
2720 "key"=>"H"
2722 array( "image"=>"button_image.png",
2723 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2724 "close"=>"]]",
2725 "sample"=>wfMsg("image_sample"),
2726 "tip"=>wfMsg("image_tip"),
2727 "key"=>"D"
2729 array( "image"=>"button_media.png",
2730 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2731 "close"=>"]]",
2732 "sample"=>wfMsg("media_sample"),
2733 "tip"=>wfMsg("media_tip"),
2734 "key"=>"M"
2736 array( "image"=>"button_math.png",
2737 "open"=>"\\<math\\>",
2738 "close"=>"\\</math\\>",
2739 "sample"=>wfMsg("math_sample"),
2740 "tip"=>wfMsg("math_tip"),
2741 "key"=>"C"
2743 array( "image"=>"button_nowiki.png",
2744 "open"=>"\\<nowiki\\>",
2745 "close"=>"\\</nowiki\\>",
2746 "sample"=>wfMsg("nowiki_sample"),
2747 "tip"=>wfMsg("nowiki_tip"),
2748 "key"=>"N"
2750 array( "image"=>"button_sig.png",
2751 "open"=>"--~~~~",
2752 "close"=>"",
2753 "sample"=>"",
2754 "tip"=>wfMsg("sig_tip"),
2755 "key"=>"Y"
2757 array( "image"=>"button_hr.png",
2758 "open"=>"\\n----\\n",
2759 "close"=>"",
2760 "sample"=>"",
2761 "tip"=>wfMsg("hr_tip"),
2762 "key"=>"R"
2765 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2767 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2768 foreach($toolarray as $tool) {
2770 $image=$wgStylePath.'/images/'.$tool['image'];
2771 $open=$tool['open'];
2772 $close=$tool['close'];
2773 $sample = addslashes( $tool['sample'] );
2775 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2776 // Older browsers show a "speedtip" type message only for ALT.
2777 // Ideally these should be different, realistically they
2778 // probably don't need to be.
2779 $tip = addslashes( $tool['tip'] );
2781 #$key = $tool["key"];
2783 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2786 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2787 $toolbar.="document.writeln(\"</div>\");\n";
2789 $toolbar.="/*]]>*/\n</script>";
2790 return $toolbar;