Category links are not part of mBodyText, so <!--LINK tags are not converted.
[mediawiki.git] / includes / Skin.php
blobdbff5d63b2a7386d4609d4834d7de73f98d05dd2
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;
49 var $postParseLinkColour = true;
51 function Skin()
53 $this->linktrail = wfMsg('linktrail');
56 function getSkinNames()
58 global $wgValidSkinNames;
59 return $wgValidSkinNames;
62 function getStylesheet()
64 return 'wikistandard.css';
66 function getSkinName() {
67 return "standard";
70 # Get/set accessor for delayed link colouring
71 function postParseLinkColour( $setting = NULL ) {
72 return wfSetVar( $this->postParseLinkColour, $setting );
75 function qbSetting()
77 global $wgOut, $wgUser;
79 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
80 $q = $wgUser->getOption( 'quickbar' );
81 if ( '' == $q ) { $q = 0; }
82 return $q;
85 function initPage( &$out )
87 $fname = 'Skin::initPage';
88 wfProfileIn( $fname );
90 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
92 $this->addMetadataLinks($out);
94 wfProfileOut( $fname );
97 function addMetadataLinks( &$out ) {
98 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
99 global $wgRightsPage, $wgRightsUrl;
101 if( $out->isArticleRelated() ) {
102 # note: buggy CC software only reads first "meta" link
103 if( $wgEnableCreativeCommonsRdf ) {
104 $out->addMetadataLink( array(
105 'title' => 'Creative Commons',
106 'type' => 'application/rdf+xml',
107 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
109 if( $wgEnableDublinCoreRdf ) {
110 $out->addMetadataLink( array(
111 'title' => 'Dublin Core',
112 'type' => 'application/rdf+xml',
113 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
116 $copyright = '';
117 if( $wgRightsPage ) {
118 $copy = Title::newFromText( $wgRightsPage );
119 if( $copy ) {
120 $copyright = $copy->getLocalURL();
123 if( !$copyright && $wgRightsUrl ) {
124 $copyright = $wgRightsUrl;
126 if( $copyright ) {
127 $out->addLink( array(
128 'rel' => 'copyright',
129 'href' => $copyright ) );
133 function outputPage( &$out ) {
134 global $wgDebugComments;
136 wfProfileIn( 'Skin::outputPage' );
137 $this->initPage( $out );
138 $out->out( $out->headElement() );
140 $out->out( "\n<body" );
141 $ops = $this->getBodyOptions();
142 foreach ( $ops as $name => $val ) {
143 $out->out( " $name='$val'" );
145 $out->out( ">\n" );
146 if ( $wgDebugComments ) {
147 $out->out( "<!-- Wiki debugging output:\n" .
148 $out->mDebugtext . "-->\n" );
150 $out->out( $this->beforeContent() );
152 $out->out( $out->mBodytext . "\n" );
154 $out->out( $this->afterContent() );
156 wfProfileClose();
157 $out->out( $out->reportTime() );
159 $out->out( "\n</body></html>" );
162 function getHeadScripts() {
163 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
164 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
165 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
166 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
167 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
168 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
170 return $r;
173 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
174 function getUserStylesheet() {
175 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
176 $sheet = $this->getStylesheet();
177 $action = $wgRequest->getText('action');
178 $s = "@import \"$wgStylePath/$sheet\";\n";
179 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
180 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
181 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
182 $s .= $wgRequest->getText('wpTextbox1');
183 } else {
184 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
185 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
188 $s .= $this->doGetUserStyles();
189 return $s."\n";
191 # placeholder, returns generated js in monobook
192 function getUserJs() {
193 return;
196 function getUserStyles()
198 global $wgOut, $wgStylePath, $wgLang;
199 $s = "<style type='text/css'>\n";
200 $s .= "/*/*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
201 $s .= $this->getUserStylesheet();
202 $s .= "/* */\n";
203 $s .= "</style>\n";
204 return $s;
207 function doGetUserStyles()
209 global $wgUser, $wgLang;
211 $csspage = $wgLang->getNsText( NS_MEDIAWIKI ) . ":" . $this->getSkinName() . ".css";
212 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
214 if ( 1 == $wgUser->getOption( 'underline' ) ) {
215 # Don't override browser settings
216 } else {
217 # CHECK MERGE @@@
218 # Force no underline
219 $s .= "a { text-decoration: none; }\n";
221 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
222 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
224 if ( 1 == $wgUser->getOption( 'justify' ) ) {
225 $s .= "#article { text-align: justify; }\n";
227 return $s;
230 function getBodyOptions()
232 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
234 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
236 if ( 0 != $wgTitle->getNamespace() ) {
237 $a = array( 'bgcolor' => '#ffffec' );
239 else $a = array( 'bgcolor' => '#FFFFFF' );
240 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
241 (!$wgTitle->isProtected() || $wgUser->isSysop()) ) {
242 $t = wfMsg( 'editthispage' );
243 $oid = $red = '';
244 if ( !empty($redirect) ) {
245 $red = "&redirect={$redirect}";
247 if ( !empty($oldid) && ! isset( $diff ) ) {
248 $oid = "&oldid={$oldid}";
250 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
251 $s = 'document.location = "' .$s .'";';
252 $a += array ('ondblclick' => $s);
255 $a['onload'] = $wgOut->getOnloadHandler();
256 return $a;
259 function getExternalLinkAttributes( $link, $text, $class='' )
261 global $wgUser, $wgOut, $wgLang;
263 $link = urldecode( $link );
264 $link = $wgLang->checkTitleEncoding( $link );
265 $link = str_replace( '_', ' ', $link );
266 $link = wfEscapeHTML( $link );
268 $r = ($class != '') ? " class='$class'" : " class='external'";
270 if ( 1 == $wgUser->getOption( 'hover' ) ) {
271 $r .= " title=\"{$link}\"";
273 return $r;
276 function getInternalLinkAttributes( $link, $text, $broken = false )
278 global $wgUser, $wgOut;
280 $link = urldecode( $link );
281 $link = str_replace( '_', ' ', $link );
282 $link = wfEscapeHTML( $link );
284 if ( $broken == 'stub' ) {
285 $r = ' class="stub"';
286 } else if ( $broken == 'yes' ) {
287 $r = ' class="new"';
288 } else {
289 $r = '';
292 if ( 1 == $wgUser->getOption( 'hover' ) ) {
293 $r .= " title=\"{$link}\"";
295 return $r;
298 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
300 global $wgUser, $wgOut;
302 if ( $broken == 'stub' ) {
303 $r = ' class="stub"';
304 } else if ( $broken == 'yes' ) {
305 $r = ' class="new"';
306 } else {
307 $r = '';
310 if ( 1 == $wgUser->getOption( 'hover' ) ) {
311 $r .= ' title ="' . $nt->getEscapedText() . '"';
313 return $r;
316 function getLogo()
318 global $wgLogo;
319 return $wgLogo;
322 # This will be called immediately after the <body> tag. Split into
323 # two functions to make it easier to subclass.
325 function beforeContent()
327 global $wgUser, $wgOut;
329 return $this->doBeforeContent();
332 function doBeforeContent()
334 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
335 $fname = 'Skin::doBeforeContent';
336 wfProfileIn( $fname );
338 $s = '';
339 $qb = $this->qbSetting();
341 if( $langlinks = $this->otherLanguages() ) {
342 $rows = 2;
343 $borderhack = '';
344 } else {
345 $rows = 1;
346 $langlinks = false;
347 $borderhack = 'class="top"';
350 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
351 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
353 $shove = ($qb != 0);
354 $left = ($qb == 1 || $qb == 3);
355 if($wgLang->isRTL()) $left = !$left;
357 if ( !$shove ) {
358 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
359 $this->logoText() . '</td>';
360 } elseif( $left ) {
361 $s .= $this->getQuickbarCompensator( $rows );
363 $l = $wgLang->isRTL() ? 'right' : 'left';
364 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
366 $s .= $this->topLinks() ;
367 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
369 $r = $wgLang->isRTL() ? "left" : "right";
370 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
371 $s .= $this->nameAndLogin();
372 $s .= "\n<br />" . $this->searchForm() . "</td>";
374 if ( $langlinks ) {
375 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
378 if ( $shove && !$left ) { # Right
379 $s .= $this->getQuickbarCompensator( $rows );
381 $s .= "</tr>\n</table>\n</div>\n";
382 $s .= "\n<div id='article'>\n";
384 if( $wgSiteNotice ) {
385 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
387 $s .= $this->pageTitle();
388 $s .= $this->pageSubtitle() ;
389 $s .= $this->getCategories();
390 wfProfileOut( $fname );
391 return $s;
394 function getCategoryLinks () {
395 global $wgOut, $wgTitle, $wgUser, $wgParser;
396 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
398 if( !$wgUseCategoryMagic ) return '' ;
399 if( count( $wgOut->mCategoryLinks ) == 0 ) return '';
401 # Taken out so that they will be displayed in previews -- TS
402 #if( !$wgOut->isArticle() ) return '';
404 $t = implode ( ' | ' , $wgOut->mCategoryLinks ) ;
405 $s = $this->makeKnownLink( 'Special:Categories',
406 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
407 . ': ' . $t;
409 if($wgUseCategoryBrowser) {
410 $s .= '<br/><hr/>';
411 $catstack = array();
412 $s.= $wgTitle->getAllParentCategories($catstack);
415 return $s;
418 function getCategories() {
419 $catlinks=$this->getCategoryLinks();
420 if(!empty($catlinks)) {
421 return "<p class='catlinks'>{$catlinks}</p>";
425 function getQuickbarCompensator( $rows = 1 )
427 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
430 # This gets called immediately before the </body> tag.
432 function afterContent()
434 global $wgUser, $wgOut, $wgServer;
435 global $wgTitle, $wgLang;
437 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
438 return $printfooter . $this->doAfterContent();
441 function printFooter() {
442 global $wgTitle;
443 $url = htmlspecialchars( $wgTitle->getFullURL() );
444 return "<p>" . wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" ) .
445 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
448 function doAfterContent()
450 global $wgUser, $wgOut, $wgLang;
451 $fname = 'Skin::doAfterContent';
452 wfProfileIn( $fname );
453 wfProfileIn( $fname.'-1' );
455 $s = "\n</div><br style=\"clear:both\" />\n";
456 $s .= "\n<div id='footer'>";
457 $s .= '<table border="0" cellspacing="0"><tr>';
459 wfProfileOut( $fname.'-1' );
460 wfProfileIn( $fname.'-2' );
462 $qb = $this->qbSetting();
463 $shove = ($qb != 0);
464 $left = ($qb == 1 || $qb == 3);
465 if($wgLang->isRTL()) $left = !$left;
467 if ( $shove && $left ) { # Left
468 $s .= $this->getQuickbarCompensator();
470 wfProfileOut( $fname.'-2' );
471 wfProfileIn( $fname.'-3' );
472 $l = $wgLang->isRTL() ? 'right' : 'left';
473 $s .= "<td class='bottom' align='$l' valign='top'>";
475 $s .= $this->bottomLinks();
476 $s .= "\n<br />" . $this->mainPageLink()
477 . ' | ' . $this->aboutLink()
478 . ' | ' . $this->specialLink( 'recentchanges' )
479 . ' | ' . $this->searchForm()
480 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
482 $s .= "</td>";
483 if ( $shove && !$left ) { # Right
484 $s .= $this->getQuickbarCompensator();
486 $s .= "</tr></table>\n</div>\n</div>\n";
488 wfProfileOut( $fname.'-3' );
489 wfProfileIn( $fname.'-4' );
490 if ( 0 != $qb ) { $s .= $this->quickBar(); }
491 wfProfileOut( $fname.'-4' );
492 wfProfileOut( $fname );
493 return $s;
496 function pageTitleLinks()
498 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
500 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
501 $action = $wgRequest->getText( 'action' );
503 $s = $this->printableLink();
504 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
506 if ( $wgOut->isArticleRelated() ) {
507 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
508 $name = $wgTitle->getDBkey();
509 $link = wfEscapeHTML( Image::wfImageUrl( $name ) );
510 $style = $this->getInternalLinkAttributes( $link, $name );
511 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
513 # This will show the "Approve" link if $wgUseApproval=true;
514 if ( isset ( $wgUseApproval ) && $wgUseApproval )
516 $t = $wgTitle->getDBkey();
517 $name = 'Approve this article' ;
518 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
519 #wfEscapeHTML( wfImageUrl( $name ) );
520 $style = $this->getExternalLinkAttributes( $link, $name );
521 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
524 if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) {
525 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
526 wfMsg( 'currentrev' ) );
529 if ( $wgUser->getNewtalk() ) {
530 # do not show "You have new messages" text when we are viewing our
531 # own talk page
533 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
534 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
535 $n =$wgUser->getName();
536 $tl = $this->makeKnownLink( $wgLang->getNsText(
537 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
538 wfMsg('newmessageslink') );
539 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
543 $undelete = $this->getUndeleteLink();
544 if( !empty( $undelete ) ) {
545 $s .= ' | '.$undelete;
547 return $s;
550 function getUndeleteLink() {
551 global $wgUser, $wgTitle, $wgLang, $action;
552 if( $wgUser->isSysop() &&
553 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
554 ($n = $wgTitle->isDeleted() ) ) {
555 return wfMsg( 'thisisdeleted',
556 $this->makeKnownLink(
557 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
558 wfMsg( 'restorelink', $n ) ) );
560 return '';
563 function printableLink()
565 global $wgOut, $wgFeedClasses, $wgRequest;
567 $baseurl = $_SERVER['REQUEST_URI'];
568 if( strpos( '?', $baseurl ) == false ) {
569 $baseurl .= '?';
570 } else {
571 $baseurl .= '&';
573 $baseurl = htmlspecialchars( $baseurl );
574 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
576 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
577 if( $wgOut->isSyndicated() ) {
578 foreach( $wgFeedClasses as $format => $class ) {
579 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
580 $s .= " | <a href=\"$feedurl\">{$format}</a>";
583 return $s;
586 function pageTitle()
588 global $wgOut, $wgTitle, $wgUser;
590 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
591 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
592 return $s;
595 function pageSubtitle()
597 global $wgOut;
599 $sub = $wgOut->getSubtitle();
600 if ( '' == $sub ) {
601 global $wgExtraSubtitle;
602 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
604 $subpages = $this->subPageSubtitle();
605 $sub .= !empty($subpages)?"</p><p class='subpages'>$subpages":'';
606 $s = "<p class='subtitle'>{$sub}</p>\n";
607 return $s;
610 function subPageSubtitle()
612 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
613 $subpages = '';
614 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
615 $ptext=$wgTitle->getPrefixedText();
616 if(preg_match('/\//',$ptext)) {
617 $links = explode('/',$ptext);
618 $c = 0;
619 $growinglink = '';
620 foreach($links as $link) {
621 $c++;
622 if ($c<count($links)) {
623 $growinglink .= $link;
624 $getlink = $this->makeLink( $growinglink, $link );
625 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
626 if ($c>1) {
627 $subpages .= ' | ';
628 } else {
629 $subpages .= '&lt; ';
631 $subpages .= $getlink;
632 $growinglink .= '/';
637 return $subpages;
640 function nameAndLogin()
642 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
644 $li = $wgLang->specialPage( 'Userlogin' );
645 $lo = $wgLang->specialPage( 'Userlogout' );
647 $s = '';
648 if ( 0 == $wgUser->getID() ) {
649 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
650 $n = $wgIP;
652 $tl = $this->makeKnownLink( $wgLang->getNsText(
653 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
654 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
656 $s .= $n . ' ('.$tl.')';
657 } else {
658 $s .= wfMsg('notloggedin');
661 $rt = $wgTitle->getPrefixedURL();
662 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
663 $q = '';
664 } else { $q = "returnto={$rt}"; }
666 $s .= "\n<br />" . $this->makeKnownLink( $li,
667 wfMsg( 'login' ), $q );
668 } else {
669 $n = $wgUser->getName();
670 $rt = $wgTitle->getPrefixedURL();
671 $tl = $this->makeKnownLink( $wgLang->getNsText(
672 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
673 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
675 $tl = " ({$tl})";
677 $s .= $this->makeKnownLink( $wgLang->getNsText(
678 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
679 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
680 "returnto={$rt}" ) . ' | ' .
681 $this->specialLink( 'preferences' );
683 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
684 wfMsg( 'help' ) );
686 return $s;
689 function getSearchLink() {
690 $searchPage =& Title::makeTitle( NS_SPECIAL, 'Search' );
691 return $searchPage->getLocalURL();
694 function escapeSearchLink() {
695 return htmlspecialchars( $this->getSearchLink() );
698 function searchForm()
700 global $wgRequest;
701 $search = $wgRequest->getText( 'search' );
703 $s = '<form name="search" class="inline" method="post" action="'
704 . $this->escapeSearchLink() . "\">\n"
705 . '<input type="text" name="search" size="19" value="'
706 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
707 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" />&nbsp;'
708 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
710 return $s;
713 function topLinks()
715 global $wgOut;
716 $sep = " |\n";
718 $s = $this->mainPageLink() . $sep
719 . $this->specialLink( 'recentchanges' );
721 if ( $wgOut->isArticleRelated() ) {
722 $s .= $sep . $this->editThisPage()
723 . $sep . $this->historyLink();
725 # Many people don't like this dropdown box
726 #$s .= $sep . $this->specialPagesList();
728 return $s;
731 function bottomLinks()
733 global $wgOut, $wgUser, $wgTitle;
734 $sep = " |\n";
736 $s = '';
737 if ( $wgOut->isArticleRelated() ) {
738 $s .= '<strong>' . $this->editThisPage() . '</strong>';
739 if ( 0 != $wgUser->getID() ) {
740 $s .= $sep . $this->watchThisPage();
742 $s .= $sep . $this->talkLink()
743 . $sep . $this->historyLink()
744 . $sep . $this->whatLinksHere()
745 . $sep . $this->watchPageLinksLink();
747 if ( $wgTitle->getNamespace() == Namespace::getUser()
748 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
751 $id=User::idFromName($wgTitle->getText());
752 $ip=User::isIP($wgTitle->getText());
754 if($id || $ip) { # both anons and non-anons have contri list
755 $s .= $sep . $this->userContribsLink();
757 if ( 0 != $wgUser->getID() ) { # show only to signed in users
758 if($id) { # can only email non-anons
759 $s .= $sep . $this->emailUserLink();
763 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
764 $s .= "\n<br />" . $this->deleteThisPage() .
765 $sep . $this->protectThisPage() .
766 $sep . $this->moveThisPage();
768 $s .= "<br />\n" . $this->otherLanguages();
770 return $s;
773 function pageStats()
775 global $wgOut, $wgLang, $wgArticle, $wgRequest;
776 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
778 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
779 if ( ! $wgOut->isArticle() ) { return ''; }
780 if ( isset( $oldid ) || isset( $diff ) ) { return ''; }
781 if ( 0 == $wgArticle->getID() ) { return ''; }
783 $s = '';
784 if ( !$wgDisableCounters ) {
785 $count = $wgLang->formatNum( $wgArticle->getCount() );
786 if ( $count ) {
787 $s = wfMsg( 'viewcount', $count );
791 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
792 require_once("Credits.php");
793 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
794 } else {
795 $s .= $this->lastModified();
798 return $s . ' ' . $this->getCopyright();
801 function getCopyright() {
802 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
805 $oldid = $wgRequest->getVal( 'oldid' );
806 $diff = $wgRequest->getVal( 'diff' );
808 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
809 $msg = 'history_copyright';
810 } else {
811 $msg = 'copyright';
814 $out = '';
815 if( $wgRightsPage ) {
816 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
817 } elseif( $wgRightsUrl ) {
818 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
819 } else {
820 # Give up now
821 return $out;
823 $out .= wfMsg( $msg, $link );
824 return $out;
827 function getCopyrightIcon() {
828 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
829 $out = '';
830 if( $wgRightsIcon ) {
831 $icon = htmlspecialchars( $wgRightsIcon );
832 if( $wgRightsUrl ) {
833 $url = htmlspecialchars( $wgRightsUrl );
834 $out .= '<a href="'.$url.'">';
836 $text = htmlspecialchars( $wgRightsText );
837 $out .= "<img src=\"$icon\" alt='$text' />";
838 if( $wgRightsUrl ) {
839 $out .= '</a>';
842 return $out;
845 function getPoweredBy() {
846 global $wgStylePath;
847 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
848 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
849 return $img;
852 function lastModified()
854 global $wgLang, $wgArticle;
856 $timestamp = $wgArticle->getTimestamp();
857 if ( $timestamp ) {
858 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
859 $s = ' ' . wfMsg( 'lastmodified', $d );
860 } else {
861 $s = '';
863 return $s;
866 function logoText( $align = '' )
868 if ( '' != $align ) { $a = ' align="'.$align.'"'; }
869 else { $a = ''; }
871 $mp = wfMsg( 'mainpage' );
872 $titleObj = Title::newFromText( $mp );
873 $s = '<a href="' . $titleObj->escapeLocalURL()
874 . '"><img'.$a.' src="'
875 . $this->getLogo() . '" alt="' . "[{$mp}]\" /></a>";
876 return $s;
879 function quickBar()
881 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
882 global $wgDisableUploads, $wgRemoteUploads;
884 $fname = 'Skin::quickBar';
885 wfProfileIn( $fname );
887 $action = $wgRequest->getText( 'action' );
888 $wpPreview = $wgRequest->getBool( 'wpPreview' );
889 $tns=$wgTitle->getNamespace();
891 $s = "\n<div id='quickbar'>";
892 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
894 $sep = "\n<br />";
895 $s .= $this->mainPageLink()
896 . $sep . $this->specialLink( 'recentchanges' )
897 . $sep . $this->specialLink( 'randompage' );
898 if ($wgUser->getID()) {
899 $s.= $sep . $this->specialLink( 'watchlist' ) ;
900 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
901 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
904 // only show watchlist link if logged in
905 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
906 $s .= "\n<br /><hr class='sep' />";
907 $articleExists = $wgTitle->getArticleId();
908 if ( $wgOut->isArticle() || $action =='edit' || $action =='history' || $wpPreview) {
909 if($wgOut->isArticle()) {
910 $s .= '<strong>' . $this->editThisPage() . '</strong>';
911 } else { # backlink to the article in edit or history mode
912 if($articleExists){ # no backlink if no article
913 switch($tns) {
914 case 0:
915 $text = wfMsg('articlepage');
916 break;
917 case 1:
918 $text = wfMsg('viewtalkpage');
919 break;
920 case 2:
921 $text = wfMsg('userpage');
922 break;
923 case 3:
924 $text = wfMsg('viewtalkpage');
925 break;
926 case 4:
927 $text = wfMsg('wikipediapage');
928 break;
929 case 5:
930 $text = wfMsg('viewtalkpage');
931 break;
932 case 6:
933 $text = wfMsg('imagepage');
934 break;
935 case 7:
936 $text = wfMsg('viewtalkpage');
937 break;
938 default:
939 $text= wfMsg('articlepage');
942 $link = $wgTitle->getText();
943 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
944 $link = $nstext . ':' . $link ;
947 $s .= $this->makeLink( $link, $text );
948 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
949 # we just throw in a "New page" text to tell the user that he's in edit mode,
950 # and to avoid messing with the separator that is prepended to the next item
951 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
957 if( $tns%2 && $action!='edit' && !$wpPreview) {
958 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit&section=new');
962 watching could cause problems in edit mode:
963 if user edits article, then loads "watch this article" in background and then saves
964 article with "Watch this article" checkbox disabled, the article is transparently
965 unwatched. Therefore we do not show the "Watch this page" link in edit mode
967 if ( 0 != $wgUser->getID() && $articleExists) {
968 if($action!='edit' && $action != 'submit' )
970 $s .= $sep . $this->watchThisPage();
972 if ( $wgTitle->userCanEdit() )
973 $s .= $sep . $this->moveThisPage();
975 if ( $wgUser->isSysop() and $articleExists ) {
976 $s .= $sep . $this->deleteThisPage() .
977 $sep . $this->protectThisPage();
979 $s .= $sep . $this->talkLink();
980 if ($articleExists && $action !='history') {
981 $s .= $sep . $this->historyLink();
983 $s.=$sep . $this->whatLinksHere();
985 if($wgOut->isArticleRelated()) {
986 $s .= $sep . $this->watchPageLinksLink();
989 if ( Namespace::getUser() == $wgTitle->getNamespace()
990 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
993 $id=User::idFromName($wgTitle->getText());
994 $ip=User::isIP($wgTitle->getText());
996 if($id||$ip) {
997 $s .= $sep . $this->userContribsLink();
999 if ( 0 != $wgUser->getID() ) {
1000 if($id) { # can only email real users
1001 $s .= $sep . $this->emailUserLink();
1005 $s .= "\n<br /><hr class='sep' />";
1008 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
1009 $s .= $this->specialLink( 'upload' ) . $sep;
1011 $s .= $this->specialLink( 'specialpages' )
1012 . $sep . $this->bugReportsLink();
1014 global $wgSiteSupportPage;
1015 if( $wgSiteSupportPage ) {
1016 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1017 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1020 $s .= "\n<br /></div>\n";
1021 wfProfileOut( $fname );
1022 return $s;
1025 function specialPagesList()
1027 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1028 require_once('SpecialPage.php');
1029 $a = array();
1030 $pages = SpecialPage::getPages();
1032 foreach ( $pages[''] as $name => $page ) {
1033 $a[$name] = $page->getDescription();
1035 if ( $wgUser->isSysop() )
1037 foreach ( $pages['sysop'] as $name => $page ) {
1038 $a[$name] = $page->getDescription();
1041 if ( $wgUser->isDeveloper() )
1043 foreach ( $pages['developer'] as $name => $page ) {
1044 $a[$name] = $page->getDescription() ;
1047 $go = wfMsg( 'go' );
1048 $sp = wfMsg( 'specialpages' );
1049 $spp = $wgLang->specialPage( 'Specialpages' );
1051 $s = '<form id="specialpages" method="get" class="inline" ' .
1052 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1053 $s .= "<select name=\"wpDropdown\">\n";
1054 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1056 foreach ( $a as $name => $desc ) {
1057 $p = $wgLang->specialPage( $name );
1058 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1060 $s .= "</select>\n";
1061 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1062 $s .= "</form>\n";
1063 return $s;
1066 function mainPageLink()
1068 $mp = wfMsg( 'mainpage' );
1069 $s = $this->makeKnownLink( $mp, $mp );
1070 return $s;
1073 function copyrightLink()
1075 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1076 wfMsg( 'copyrightpagename' ) );
1077 return $s;
1080 function aboutLink()
1082 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1083 wfMsg( 'aboutwikipedia' ) );
1084 return $s;
1088 function disclaimerLink()
1090 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1091 wfMsg( 'disclaimers' ) );
1092 return $s;
1095 function editThisPage()
1097 global $wgOut, $wgTitle, $wgRequest;
1099 $oldid = $wgRequest->getVal( 'oldid' );
1100 $diff = $wgRequest->getVal( 'diff' );
1101 $redirect = $wgRequest->getVal( 'redirect' );
1103 if ( ! $wgOut->isArticleRelated() ) {
1104 $s = wfMsg( 'protectedpage' );
1105 } else {
1106 $n = $wgTitle->getPrefixedText();
1107 if ( $wgTitle->userCanEdit() ) {
1108 $t = wfMsg( 'editthispage' );
1109 } else {
1110 #$t = wfMsg( "protectedpage" );
1111 $t = wfMsg( 'viewsource' );
1113 $oid = $red = '';
1115 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1116 if ( $oldid && ! isset( $diff ) ) {
1117 $oid = "&oldid={$oldid}";
1119 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1121 return $s;
1124 function deleteThisPage()
1126 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1128 $diff = $wgRequest->getVal( 'diff' );
1129 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1130 $n = $wgTitle->getPrefixedText();
1131 $t = wfMsg( 'deletethispage' );
1133 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1134 } else {
1135 $s = '';
1137 return $s;
1140 function protectThisPage()
1142 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1144 $diff = $wgRequest->getVal( 'diff' );
1145 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1146 $n = $wgTitle->getPrefixedText();
1148 if ( $wgTitle->isProtected() ) {
1149 $t = wfMsg( 'unprotectthispage' );
1150 $q = 'action=unprotect';
1151 } else {
1152 $t = wfMsg( 'protectthispage' );
1153 $q = 'action=protect';
1155 $s = $this->makeKnownLink( $n, $t, $q );
1156 } else {
1157 $s = '';
1159 return $s;
1162 function watchThisPage()
1164 global $wgUser, $wgOut, $wgTitle;
1166 if ( $wgOut->isArticleRelated() ) {
1167 $n = $wgTitle->getPrefixedText();
1169 if ( $wgTitle->userIsWatching() ) {
1170 $t = wfMsg( 'unwatchthispage' );
1171 $q = 'action=unwatch';
1172 } else {
1173 $t = wfMsg( 'watchthispage' );
1174 $q = 'action=watch';
1176 $s = $this->makeKnownLink( $n, $t, $q );
1177 } else {
1178 $s = wfMsg( 'notanarticle' );
1180 return $s;
1183 function moveThisPage()
1185 global $wgTitle, $wgLang;
1187 if ( $wgTitle->userCanEdit() ) {
1188 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1189 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1190 } // no message if page is protected - would be redundant
1191 return $s;
1194 function historyLink()
1196 global $wgTitle;
1198 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1199 wfMsg( 'history' ), 'action=history' );
1200 return $s;
1203 function whatLinksHere()
1205 global $wgTitle, $wgLang;
1207 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1208 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1209 return $s;
1212 function userContribsLink()
1214 global $wgTitle, $wgLang;
1216 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1217 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1218 return $s;
1221 function emailUserLink()
1223 global $wgTitle, $wgLang;
1225 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1226 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1227 return $s;
1230 function watchPageLinksLink()
1232 global $wgOut, $wgTitle, $wgLang;
1234 if ( ! $wgOut->isArticleRelated() ) {
1235 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1236 } else {
1237 $s = $this->makeKnownLink( $wgLang->specialPage(
1238 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1239 'target=' . $wgTitle->getPrefixedURL() );
1241 return $s;
1244 function otherLanguages()
1246 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1248 $a = $wgOut->getLanguageLinks();
1249 if ( 0 == count( $a ) ) {
1250 if ( !$wgUseNewInterlanguage ) return '';
1251 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1252 if ( $ns != 0 AND $ns != 1 ) return '' ;
1253 $pn = 'Intl' ;
1254 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1255 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1256 wfMsg( 'intl' ) , $x );
1259 if ( !$wgUseNewInterlanguage ) {
1260 $s = wfMsg( 'otherlanguages' ) . ': ';
1261 } else {
1262 global $wgLanguageCode ;
1263 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1264 $x .= '&xl='.$wgLanguageCode ;
1265 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1266 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1269 $s = wfMsg( 'otherlanguages' ) . ': ';
1270 $first = true;
1271 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1272 foreach( $a as $l ) {
1273 if ( ! $first ) { $s .= ' | '; }
1274 $first = false;
1276 $nt = Title::newFromText( $l );
1277 $url = $nt->getFullURL();
1278 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1280 if ( '' == $text ) { $text = $l; }
1281 $style = $this->getExternalLinkAttributes( $l, $text );
1282 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1284 if($wgLang->isRTL()) $s .= '</span>';
1285 return $s;
1288 function bugReportsLink()
1290 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1291 wfMsg( 'bugreports' ) );
1292 return $s;
1295 function dateLink()
1297 global $wgLinkCache;
1298 $t1 = Title::newFromText( gmdate( 'F j' ) );
1299 $t2 = Title::newFromText( gmdate( 'Y' ) );
1301 $wgLinkCache->suspend();
1302 $id = $t1->getArticleID();
1303 $wgLinkCache->resume();
1305 if ( 0 == $id ) {
1306 $s = $this->makeBrokenLink( $t1->getText() );
1307 } else {
1308 $s = $this->makeKnownLink( $t1->getText() );
1310 $s .= ', ';
1312 $wgLinkCache->suspend();
1313 $id = $t2->getArticleID();
1314 $wgLinkCache->resume();
1316 if ( 0 == $id ) {
1317 $s .= $this->makeBrokenLink( $t2->getText() );
1318 } else {
1319 $s .= $this->makeKnownLink( $t2->getText() );
1321 return $s;
1324 function talkLink()
1326 global $wgLang, $wgTitle, $wgLinkCache;
1328 $tns = $wgTitle->getNamespace();
1329 if ( -1 == $tns ) { return ''; }
1331 $pn = $wgTitle->getText();
1332 $tp = wfMsg( 'talkpage' );
1333 if ( Namespace::isTalk( $tns ) ) {
1334 $lns = Namespace::getSubject( $tns );
1335 switch($tns) {
1336 case 1:
1337 $text = wfMsg('articlepage');
1338 break;
1339 case 3:
1340 $text = wfMsg('userpage');
1341 break;
1342 case 5:
1343 $text = wfMsg('wikipediapage');
1344 break;
1345 case 7:
1346 $text = wfMsg('imagepage');
1347 break;
1348 default:
1349 $text= wfMsg('articlepage');
1351 } else {
1353 $lns = Namespace::getTalk( $tns );
1354 $text=$tp;
1356 $n = $wgLang->getNsText( $lns );
1357 if ( '' == $n ) { $link = $pn; }
1358 else { $link = $n.':'.$pn; }
1360 $wgLinkCache->suspend();
1361 $s = $this->makeLink( $link, $text );
1362 $wgLinkCache->resume();
1364 return $s;
1367 function commentLink()
1369 global $wgLang, $wgTitle, $wgLinkCache;
1371 $tns = $wgTitle->getNamespace();
1372 if ( -1 == $tns ) { return ''; }
1374 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1376 # assert Namespace::isTalk( $lns )
1378 $n = $wgLang->getNsText( $lns );
1379 $pn = $wgTitle->getText();
1381 $link = $n.':'.$pn;
1383 $wgLinkCache->suspend();
1384 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit&section=new');
1385 $wgLinkCache->resume();
1387 return $s;
1390 # After all the page content is transformed into HTML, it makes
1391 # a final pass through here for things like table backgrounds.
1393 function transformContent( $text )
1395 return $text;
1398 # Note: This function MUST call getArticleID() on the link,
1399 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1401 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1402 wfProfileIn( 'Skin::makeLink' );
1403 $nt = Title::newFromText( $title );
1404 if ($nt) {
1405 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1406 } else {
1407 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1408 $result = $text == "" ? $title : $text;
1411 wfProfileOut( 'Skin::makeLink' );
1412 return $result;
1415 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1416 $nt = Title::newFromText( $title );
1417 if ($nt) {
1418 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1419 } else {
1420 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1421 return $text == '' ? $title : $text;
1425 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1426 $nt = Title::newFromText( $title );
1427 if ($nt) {
1428 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1429 } else {
1430 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1431 return $text == '' ? $title : $text;
1435 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1436 $nt = Title::newFromText( $title );
1437 if ($nt) {
1438 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1439 } else {
1440 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1441 return $text == '' ? $title : $text;
1445 # Pass a title object, not a title string
1446 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1448 global $wgOut, $wgUser;
1449 $fname = 'Skin::makeLinkObj';
1451 if ( $nt->isExternal() ) {
1452 $u = $nt->getFullURL();
1453 $link = $nt->getPrefixedURL();
1454 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1455 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1457 $inside = '';
1458 if ( '' != $trail ) {
1459 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1460 $inside = $m[1];
1461 $trail = $m[2];
1464 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1465 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1466 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1467 } elseif ( ( -1 == $nt->getNamespace() ) ||
1468 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1469 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1470 } else {
1471 if ( $this->postParseLinkColour() ) {
1472 $inside = '';
1473 if ( '' != $trail ) {
1474 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1475 $inside = $m[1];
1476 $trail = $m[2];
1480 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1481 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1482 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1483 } else {
1484 # Work out link colour immediately
1485 $aid = $nt->getArticleID() ;
1486 if ( 0 == $aid ) {
1487 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1488 } else {
1489 $threshold = $wgUser->getOption('stubthreshold') ;
1490 if ( $threshold > 0 ) {
1491 $dbr =& wfGetDB( DB_SLAVE );
1492 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1493 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1494 if ( $s !== false ) {
1495 $size = $s->x;
1496 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1497 $size = $threshold*2 ; # Really big
1499 $dbr->freeResult( $res );
1500 } else {
1501 $size = $threshold*2 ; # Really big
1503 } else {
1504 $size = 1 ;
1506 if ( $size < $threshold ) {
1507 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1508 } else {
1509 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1514 return $retVal;
1517 # Pass a title object, not a title string
1518 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1520 global $wgOut, $wgTitle, $wgInputEncoding;
1522 $fname = 'Skin::makeKnownLinkObj';
1523 wfProfileIn( $fname );
1525 if ( !is_object( $nt ) ) {
1526 return $text;
1528 $link = $nt->getPrefixedURL();
1530 if ( '' == $link ) {
1531 $u = '';
1532 if ( '' == $text ) {
1533 $text = htmlspecialchars( $nt->getFragment() );
1535 } else {
1536 $u = $nt->escapeLocalURL( $query );
1538 if ( '' != $nt->getFragment() ) {
1539 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT, $wgInputEncoding ) );
1540 $replacearray = array(
1541 '%3A' => ':',
1542 '%' => '.'
1544 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1546 if ( '' == $text ) {
1547 $text = htmlspecialchars( $nt->getPrefixedText() );
1549 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1551 $inside = '';
1552 if ( '' != $trail ) {
1553 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1554 $inside = $m[1];
1555 $trail = $m[2];
1558 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1559 wfProfileOut( $fname );
1560 return $r;
1563 # Pass a title object, not a title string
1564 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1566 global $wgOut, $wgUser;
1568 $fname = 'Skin::makeBrokenLinkObj';
1569 wfProfileIn( $fname );
1571 if ( '' == $query ) {
1572 $q = 'action=edit';
1573 } else {
1574 $q = 'action=edit&'.$query;
1576 $u = $nt->escapeLocalURL( $q );
1578 if ( '' == $text ) {
1579 $text = htmlspecialchars( $nt->getPrefixedText() );
1581 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1583 $inside = '';
1584 if ( '' != $trail ) {
1585 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1586 $inside = $m[1];
1587 $trail = $m[2];
1590 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1591 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1592 } else {
1593 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1596 wfProfileOut( $fname );
1597 return $s;
1600 # Pass a title object, not a title string
1601 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1603 global $wgOut, $wgUser;
1605 $link = $nt->getPrefixedURL();
1607 $u = $nt->escapeLocalURL( $query );
1609 if ( '' == $text ) {
1610 $text = htmlspecialchars( $nt->getPrefixedText() );
1612 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1614 $inside = '';
1615 if ( '' != $trail ) {
1616 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1617 $inside = $m[1];
1618 $trail = $m[2];
1621 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1622 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1623 } else {
1624 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1626 return $s;
1629 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1631 $u = $nt->escapeLocalURL( $query );
1632 if ( '' == $text ) {
1633 $text = htmlspecialchars( $nt->getPrefixedText() );
1635 $inside = '';
1636 if ( '' != $trail ) {
1637 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1638 $inside = $m[1];
1639 $trail = $m[2];
1642 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1645 /* these are used extensively in SkinPHPTal, but also some other places */
1646 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1647 $title = Title::makeTitle( NS_SPECIAL, $name );
1648 $this->checkTitle($title, $name);
1649 return $title->getLocalURL( $urlaction );
1651 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1652 $title = Title::newFromText( $name );
1653 $title = $title->getTalkPage();
1654 $this->checkTitle($title, $name);
1655 return $title->getLocalURL( $urlaction );
1657 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1658 $title = Title::newFromText( $name );
1659 $title= $title->getSubjectPage();
1660 $this->checkTitle($title, $name);
1661 return $title->getLocalURL( $urlaction );
1663 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1664 $title = Title::newFromText( wfMsg($name) );
1665 $this->checkTitle($title, $name);
1666 return $title->getLocalURL( $urlaction );
1668 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1669 $title = Title::newFromText( $name );
1670 $this->checkTitle($title, $name);
1671 return $title->getLocalURL( $urlaction );
1673 # this can be passed the NS number as defined in Language.php
1674 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1675 $title = Title::makeTitle( $namespace, $name );
1676 $this->checkTitle($title, $name);
1677 return $title->getLocalURL( $urlaction );
1680 /* these return an array with the 'href' and boolean 'exists' */
1681 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1682 $title = Title::newFromText( $name );
1683 $this->checkTitle($title, $name);
1684 return array(
1685 'href' => $title->getLocalURL( $urlaction ),
1686 'exists' => $title->getArticleID() != 0?true:false
1689 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1690 $title = Title::newFromText( $name );
1691 $title = $title->getTalkPage();
1692 $this->checkTitle($title, $name);
1693 return array(
1694 'href' => $title->getLocalURL( $urlaction ),
1695 'exists' => $title->getArticleID() != 0?true:false
1698 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1699 $title = Title::newFromText( $name );
1700 $title= $title->getSubjectPage();
1701 $this->checkTitle($title, $name);
1702 return array(
1703 'href' => $title->getLocalURL( $urlaction ),
1704 'exists' => $title->getArticleID() != 0?true:false
1707 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1708 $title = Title::newFromText( wfMsg($name) );
1709 $this->checkTitle($title, $name);
1710 return array(
1711 'href' => $title->getLocalURL( $urlaction ),
1712 'exists' => $title->getArticleID() != 0?true:false
1716 # make sure we have some title to operate on
1717 /*static*/ function checkTitle ( &$title, &$name ) {
1718 if(!is_object($title)) {
1719 $title = Title::newFromText( $name );
1720 if(!is_object($title)) {
1721 $title = Title::newFromText( '--error: link target missing--' );
1726 function fnamePart( $url )
1728 $basename = strrchr( $url, '/' );
1729 if ( false === $basename ) { $basename = $url; }
1730 else { $basename = substr( $basename, 1 ); }
1731 return wfEscapeHTML( $basename );
1734 function makeImage( $url, $alt = '' )
1736 global $wgOut;
1738 if ( '' == $alt ) { $alt = $this->fnamePart( $url ); }
1739 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1740 return $s;
1743 function makeImageLink( $name, $url, $alt = '' ) {
1744 $nt = Title::makeTitle( Namespace::getImage(), $name );
1745 return $this->makeImageLinkObj( $nt, $alt );
1748 function makeImageLinkObj( $nt, $alt = '' ) {
1749 global $wgLang, $wgUseImageResize;
1750 $img = Image::newFromTitle( $nt );
1751 $url = $img->getURL();
1753 $align = '';
1754 $prefix = $postfix = '';
1756 if ( $wgUseImageResize ) {
1757 # Check if the alt text is of the form "options|alt text"
1758 # Options are:
1759 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1760 # * left no resizing, just left align. label is used for alt= only
1761 # * right same, but right aligned
1762 # * none same, but not aligned
1763 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1764 # * center center the image
1765 # * framed Keep original image size, no magnify-button.
1767 $part = explode( '|', $alt);
1769 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1770 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1771 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1772 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1773 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1774 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1775 $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
1776 $alt = $part[count($part)-1];
1778 $height = $framed = $thumb = false;
1779 $manual_thumb = "" ;
1781 foreach( $part as $key => $val ) {
1782 $val_parts = explode ( "=" , $val , 2 ) ;
1783 $left_part = array_shift ( $val_parts ) ;
1784 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1785 $thumb=true;
1786 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1787 # use manually specified thumbnail
1788 $thumb=true;
1789 $manual_thumb = array_shift ( $val_parts ) ;
1790 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1791 # remember to set an alignment, don't render immediately
1792 $align = 'right';
1793 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1794 # remember to set an alignment, don't render immediately
1795 $align = 'left';
1796 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1797 # remember to set an alignment, don't render immediately
1798 $align = 'center';
1799 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1800 # remember to set an alignment, don't render immediately
1801 $align = 'none';
1802 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1803 # $match is the image width in pixels
1804 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1805 $width = intval( $m[1] );
1806 $height = intval( $m[2] );
1807 } else {
1808 $width = intval($match);
1810 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1811 $framed=true;
1814 if ( 'center' == $align )
1816 $prefix = '<span style="text-align: center">';
1817 $postfix = '</span>';
1818 $align = 'none';
1821 if ( $thumb || $framed ) {
1823 # Create a thumbnail. Alignment depends on language
1824 # writing direction, # right aligned for left-to-right-
1825 # languages ("Western languages"), left-aligned
1826 # for right-to-left-languages ("Semitic languages")
1828 # If thumbnail width has not been provided, it is set
1829 # here to 180 pixels
1830 if ( $align == '' ) {
1831 $align = $wgLang->isRTL() ? 'left' : 'right';
1833 if ( ! isset($width) ) {
1834 $width = 180;
1836 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1838 } elseif ( isset($width) ) {
1840 # Create a resized image, without the additional thumbnail
1841 # features
1843 if ( ( ! $height === false )
1844 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1845 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1846 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1847 $width = $img->getWidth() * $height / $img->getHeight();
1849 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1851 } # endif $wgUseImageResize
1853 if ( empty( $alt ) ) {
1854 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1856 $alt = htmlspecialchars( $alt );
1858 $u = $nt->escapeLocalURL();
1859 if ( $url == '' )
1861 $s = wfMsg( 'missingimage', $img->getName() );
1862 $s .= "<br>{$alt}<br>{$url}<br>\n";
1863 } else {
1864 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1865 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1867 if ( '' != $align ) {
1868 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1870 return str_replace("\n", ' ',$prefix.$s.$postfix);
1874 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1875 global $wgStylePath, $wgLang;
1876 # $image = Title::makeTitle( Namespace::getImage(), $name );
1877 $url = $img->getURL();
1879 #$label = htmlspecialchars( $label );
1880 $alt = preg_replace( '/<[^>]*>/', '', $label);
1881 $alt = htmlspecialchars( $alt );
1883 if ( $img->exists() )
1885 $width = $img->getWidth();
1886 $height = $img->getHeight();
1887 } else {
1888 $width = $height = 200;
1890 if ( $framed )
1892 // Use image dimensions, don't scale
1893 $boxwidth = $width;
1894 $oboxwidth = $boxwidth + 2;
1895 $boxheight = $height;
1896 $thumbUrl = $url;
1897 } else {
1898 $h = intval( $height/($width/$boxwidth) );
1899 $oboxwidth = $boxwidth + 2;
1900 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1902 $boxwidth *= $boxheight/$h;
1903 } else {
1904 $boxheight = $h;
1906 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1909 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1911 $manual_title = Title::makeTitle( Namespace::getImage(), $manual_thumb ); #new Title ( $manual_thumb ) ;
1912 $manual_img = Image::newFromTitle( $manual_title );
1913 $thumbUrl = $manual_img->getURL();
1914 if ( $manual_img->exists() )
1916 $width = $manual_img->getWidth();
1917 $height = $manual_img->getHeight();
1918 $boxwidth = $width ;
1919 $boxheight = $height ;
1920 $oboxwidth = $boxwidth + 2 ;
1924 $u = $img->getEscapeLocalURL();
1926 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1927 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1928 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1930 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1931 if ( $thumbUrl == '' ) {
1932 $s .= wfMsg( 'missingimage', $img->getName() );
1933 $zoomicon = '';
1934 } else {
1935 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1936 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1937 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1938 if ( $framed ) {
1939 $zoomicon="";
1940 } else {
1941 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1942 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1943 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1944 'width="15" height="11" alt="'.$more.'" /></a></div>';
1947 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1948 return str_replace("\n", ' ', $s);
1951 function makeMediaLink( $name, $url, $alt = "" ) {
1952 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1953 return $this->makeMediaLinkObj( $nt, $alt );
1956 function makeMediaLinkObj( $nt, $alt = "" )
1958 if ( ! isset( $nt ) )
1960 ### HOTFIX. Instead of breaking, return empty string.
1961 $s = $alt;
1962 } else {
1963 $name = $nt->getDBKey();
1964 $url = Image::wfImageUrl( $name );
1965 if ( empty( $alt ) ) {
1966 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1969 $u = htmlspecialchars( $url );
1970 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1972 return $s;
1975 function specialLink( $name, $key = "" )
1977 global $wgLang;
1979 if ( '' == $key ) { $key = strtolower( $name ); }
1980 $pn = $wgLang->ucfirst( $name );
1981 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1982 wfMsg( $key ) );
1985 function makeExternalLink( $url, $text, $escape = true ) {
1986 $style = $this->getExternalLinkAttributes( $url, $text );
1987 $url = htmlspecialchars( $url );
1988 if( $escape ) {
1989 $text = htmlspecialchars( $text );
1991 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
1994 # Called by history lists and recent changes
1997 # Returns text for the start of the tabular part of RC
1998 function beginRecentChangesList()
2000 $this->rc_cache = array() ;
2001 $this->rcMoveIndex = 0;
2002 $this->rcCacheIndex = 0 ;
2003 $this->lastdate = '';
2004 $this->rclistOpen = false;
2005 return '';
2008 function beginImageHistoryList()
2010 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2011 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2012 return $s;
2015 # Returns text for the end of RC
2016 # If enhanced RC is in use, returns pretty much all the text
2017 function endRecentChangesList()
2019 $s = $this->recentChangesBlock() ;
2020 if( $this->rclistOpen ) {
2021 $s .= "</ul>\n";
2023 return $s;
2026 # Enhanced RC ungrouped line
2027 function recentChangesBlockLine ( $rcObj )
2029 global $wgStylePath, $wgLang ;
2031 # Get rc_xxxx variables
2032 extract( $rcObj->mAttribs ) ;
2033 $curIdEq = 'curid='.$rc_cur_id;
2035 # Spacer image
2036 $r = '' ;
2038 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2039 $r .= '<tt>' ;
2041 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2042 $r .= '&nbsp;&nbsp;';
2043 } else {
2044 # M & N (minor & new)
2045 $M = wfMsg( 'minoreditletter' );
2046 $N = wfMsg( 'newpageletter' );
2048 if ( $rc_type == RC_NEW ) {
2049 $r .= $N ;
2050 } else {
2051 $r .= '&nbsp;' ;
2053 if ( $rc_minor ) {
2054 $r .= $M ;
2055 } else {
2056 $r .= '&nbsp;' ;
2060 # Timestamp
2061 $r .= ' '.$rcObj->timestamp.' ' ;
2062 $r .= '</tt>' ;
2064 # Article link
2065 $link = $rcObj->link ;
2066 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2067 $r .= $link ;
2069 # Diff
2070 $r .= ' (' ;
2071 $r .= $rcObj->difflink ;
2072 $r .= '; ' ;
2074 # Hist
2075 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2077 # User/talk
2078 $r .= ') . . '.$rcObj->userlink ;
2079 $r .= $rcObj->usertalklink ;
2081 # Comment
2082 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2083 $rc_comment=$this->formatComment($rc_comment);
2084 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2087 $r .= "<br />\n" ;
2088 return $r ;
2091 # Enhanced RC group
2092 function recentChangesBlockGroup ( $block )
2094 global $wgStylePath, $wgLang ;
2096 $r = '' ;
2097 $M = wfMsg( 'minoreditletter' );
2098 $N = wfMsg( 'newpageletter' );
2100 # Collate list of users
2101 $isnew = false ;
2102 $userlinks = array () ;
2103 foreach ( $block AS $rcObj ) {
2104 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2105 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2106 $u = $rcObj->userlink ;
2107 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2108 $userlinks[$u]++ ;
2111 # Sort the list and convert to text
2112 krsort ( $userlinks ) ;
2113 asort ( $userlinks ) ;
2114 $users = array () ;
2115 foreach ( $userlinks as $userlink => $count) {
2116 $text = $userlink ;
2117 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2118 array_push ( $users , $text ) ;
2120 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2122 # Arrow
2123 $rci = 'RCI'.$this->rcCacheIndex ;
2124 $rcl = 'RCL'.$this->rcCacheIndex ;
2125 $rcm = 'RCM'.$this->rcCacheIndex ;
2126 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2127 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2128 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2129 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2130 $r .= $tl ;
2132 # Main line
2133 # M/N
2134 $r .= '<tt>' ;
2135 if ( $isnew ) $r .= $N ;
2136 else $r .= '&nbsp;' ;
2137 $r .= '&nbsp;' ; # Minor
2139 # Timestamp
2140 $r .= ' '.$block[0]->timestamp.' ' ;
2141 $r .= '</tt>' ;
2143 # Article link
2144 $link = $block[0]->link ;
2145 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2146 $r .= $link ;
2148 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2149 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2150 # Changes
2151 $r .= ' ('.count($block).' ' ;
2152 if ( $isnew ) $r .= wfMsg('changes');
2153 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2154 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2155 $r .= '; ' ;
2157 # History
2158 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2159 $r .= ')' ;
2162 $r .= $users ;
2163 $r .= "<br />\n" ;
2165 # Sub-entries
2166 $r .= '<div id="'.$rci.'" style="display:none">' ;
2167 foreach ( $block AS $rcObj ) {
2168 # Get rc_xxxx variables
2169 extract( $rcObj->mAttribs );
2171 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2172 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2173 if ( $rc_new ) $r .= $N ;
2174 else $r .= '&nbsp;' ;
2175 if ( $rc_minor ) $r .= $M ;
2176 else $r .= '&nbsp;' ;
2177 $r .= '</tt>' ;
2179 $o = '' ;
2180 if ( $rc_last_oldid != 0 ) {
2181 $o = 'oldid='.$rc_last_oldid ;
2183 if ( $rc_type == RC_LOG ) {
2184 $link = $rcObj->timestamp ;
2185 } else {
2186 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2188 $link = '<tt>'.$link.'</tt>' ;
2190 $r .= $link ;
2191 $r .= ' (' ;
2192 $r .= $rcObj->curlink ;
2193 $r .= '; ' ;
2194 $r .= $rcObj->lastlink ;
2195 $r .= ') . . '.$rcObj->userlink ;
2196 $r .= $rcObj->usertalklink ;
2197 if ( $rc_comment != '' ) {
2198 $rc_comment=$this->formatComment($rc_comment);
2199 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2201 $r .= "<br />\n" ;
2203 $r .= "</div>\n" ;
2205 $this->rcCacheIndex++ ;
2206 return $r ;
2209 # If enhanced RC is in use, this function takes the previously cached
2210 # RC lines, arranges them, and outputs the HTML
2211 function recentChangesBlock ()
2213 global $wgStylePath ;
2214 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2215 $blockOut = '';
2216 foreach ( $this->rc_cache AS $secureName => $block ) {
2217 if ( count ( $block ) < 2 ) {
2218 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2219 } else {
2220 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2224 return '<div>'.$blockOut.'</div>' ;
2227 # Called in a loop over all displayed RC entries
2228 # Either returns the line, or caches it for later use
2229 function recentChangesLine( &$rc, $watched = false )
2231 global $wgUser ;
2232 $usenew = $wgUser->getOption( 'usenewrc' );
2233 if ( $usenew )
2234 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2235 else
2236 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2237 return $line ;
2240 function recentChangesLineOld( &$rc, $watched = false )
2242 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2244 # Extract DB fields into local scope
2245 extract( $rc->mAttribs );
2246 $curIdEq = 'curid=' . $rc_cur_id;
2248 # Make date header if necessary
2249 $date = $wgLang->date( $rc_timestamp, true);
2250 $s = '';
2251 if ( $date != $this->lastdate ) {
2252 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2253 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2254 $this->lastdate = $date;
2255 $this->rclistOpen = true;
2257 $s .= '<li> ';
2259 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2260 # Diff
2261 $s .= '(' . wfMsg( 'diff' ) . ') (';
2262 # Hist
2263 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2264 ') . . ';
2266 # "[[x]] moved to [[y]]"
2267 if ( $rc_type == RC_MOVE ) {
2268 $msg = '1movedto2';
2269 } else {
2270 $msg = '1movedto2_redir';
2272 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2273 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2274 } else {
2275 # Diff link
2276 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2277 $diffLink = wfMsg( 'diff' );
2278 } else {
2279 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2280 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid ,'' ,'' , ' tabindex="'.$rc->counter.'"');
2282 $s .= '('.$diffLink.') (';
2284 # History link
2285 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2286 $s .= ') . . ';
2288 # M and N (minor and new)
2289 $M = wfMsg( 'minoreditletter' );
2290 $N = wfMsg( 'newpageletter' );
2291 if ( $rc_minor ) { $s .= ' <strong>'.$M.'</strong>'; }
2292 if ( $rc_type == RC_NEW ) { $s .= '<strong>'.$N.'</strong>'; }
2294 # Article link
2295 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2297 if ( $watched ) {
2298 $articleLink = '<strong>'.$articleLink.'</strong>';
2300 $s .= ' '.$articleLink;
2304 # Timestamp
2305 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2307 # User link (or contributions for unregistered users)
2308 if ( 0 == $rc_user ) {
2309 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2310 $rc_user_text, 'target=' . $rc_user_text );
2311 } else {
2312 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2314 $s .= $userLink;
2316 # User talk link
2317 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2318 global $wgDisableAnonTalk;
2319 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2320 $userTalkLink = '';
2321 } else {
2322 $utns=$wgLang->getNsText(NS_USER_TALK);
2323 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2325 # Block link
2326 $blockLink='';
2327 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2328 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2329 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2332 if($blockLink) {
2333 if($userTalkLink) $userTalkLink .= ' | ';
2334 $userTalkLink .= $blockLink;
2336 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2338 # Add comment
2339 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2340 $rc_comment=$this->formatComment($rc_comment);
2341 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2343 $s .= "</li>\n";
2345 return $s;
2348 # function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
2349 function recentChangesLineNew( &$baseRC, $watched = false )
2351 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2353 # Create a specialised object
2354 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2356 # Extract fields from DB into the function scope (rc_xxxx variables)
2357 extract( $rc->mAttribs );
2358 $curIdEq = 'curid=' . $rc_cur_id;
2360 # If it's a new day, add the headline and flush the cache
2361 $date = $wgLang->date( $rc_timestamp, true);
2362 $ret = '' ;
2363 if ( $date != $this->lastdate ) {
2364 # Process current cache
2365 $ret = $this->recentChangesBlock () ;
2366 $this->rc_cache = array() ;
2367 $ret .= "<h4>{$date}</h4>\n";
2368 $this->lastdate = $date;
2371 # Make article link
2372 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2373 if ( $rc_type == RC_MOVE ) {
2374 $msg = "1movedto2";
2375 } else {
2376 $msg = "1movedto2_redir";
2378 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2379 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2380 } else {
2381 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2384 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2385 $rc->watched = $watched ;
2386 $rc->link = $clink ;
2387 $rc->timestamp = $time;
2389 # Make "cur" and "diff" links
2390 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2391 $curLink = wfMsg( 'cur' );
2392 $diffLink = wfMsg( 'diff' );
2393 } else {
2394 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2395 $aprops = ' tabindex="'.$baseRC->counter.'"';
2396 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2397 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2400 # Make "last" link
2401 $titleObj = $rc->getTitle();
2402 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2403 $lastLink = wfMsg( 'last' );
2404 } else {
2405 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2406 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2409 # Make user link (or user contributions for unregistered users)
2410 if ( 0 == $rc_user ) {
2411 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2412 $rc_user_text, 'target=' . $rc_user_text );
2413 } else {
2414 $userLink = $this->makeLink( $wgLang->getNsText(
2415 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2418 $rc->userlink = $userLink ;
2419 $rc->lastlink = $lastLink ;
2420 $rc->curlink = $curLink ;
2421 $rc->difflink = $diffLink;
2424 # Make user talk link
2425 $utns=$wgLang->getNsText(NS_USER_TALK);
2426 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2427 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2429 global $wgDisableAnonTalk;
2430 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2431 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2432 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2433 if( $wgDisableAnonTalk )
2434 $rc->usertalklink = ' ('.$blockLink.')';
2435 else
2436 $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
2437 } else {
2438 if( $wgDisableAnonTalk && ($rc_user == 0) )
2439 $rc->usertalklink = '';
2440 else
2441 $rc->usertalklink = ' ('.$userTalkLink.')';
2444 # Put accumulated information into the cache, for later display
2445 # Page moves go on their own line
2446 $title = $rc->getTitle();
2447 $secureName = $title->getPrefixedDBkey();
2448 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2449 # Use an @ character to prevent collision with page names
2450 $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
2451 } else {
2452 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2453 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2455 return $ret;
2458 function endImageHistoryList()
2460 $s = "</ul>\n";
2461 return $s;
2464 /* This function is called by all recent changes variants, by the page history,
2465 and by the user contributions list. It is responsible for formatting edit
2466 comments. It escapes any HTML in the comment, but adds some CSS to format
2467 auto-generated comments (from section editing) and formats [[wikilinks]].
2468 Main author: Erik Möller (moeller@scireview.de)
2470 function formatComment($comment)
2472 global $wgLang;
2473 $comment=wfEscapeHTML($comment);
2475 # The pattern for autogen comments is / * foo * /, which makes for
2476 # some nasty regex.
2477 # We look for all comments, match any text before and after the comment,
2478 # add a separator where needed and format the comment itself with CSS
2479 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2480 $pre=$match[1];
2481 $auto=$match[2];
2482 $post=$match[3];
2483 $sep='-';
2484 if($pre) { $auto = $sep.' '.$auto; }
2485 if($post) { $auto .= ' '.$sep; }
2486 $auto='<span class="autocomment">'.$auto.'</span>';
2487 $comment=$pre.$auto.$post;
2490 # format regular and media links - all other wiki formatting
2491 # is ignored
2492 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2493 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\]/',$comment,$match)) {
2494 # Handle link renaming [[foo|text]] will show link as "text"
2495 if(isset($match[3]) ) {
2496 $text = $match[3];
2497 } else {
2498 $text = $match[1];
2500 if ( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2501 # Media link
2502 $comment = preg_replace( '/\[\[(.*?)\]\]/', $this->makeMediaLink( $submatch[1], "", $text ),
2503 $comment, 1 );
2504 } else {
2505 # Other kind of link
2506 $comment = preg_replace('/\[\[(.*?)\]\]/', $this->makeLink( $match[1], $match[1] ),
2507 $comment , 1);
2510 return $comment;
2513 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2515 global $wgUser, $wgLang, $wgTitle;
2517 $datetime = $wgLang->timeanddate( $timestamp, true );
2518 $del = wfMsg( 'deleteimg' );
2519 $delall = wfMsg( 'deleteimgcompletely' );
2520 $cur = wfMsg( 'cur' );
2522 if ( $iscur ) {
2523 $url = Image::wfImageUrl( $img );
2524 $rlink = $cur;
2525 if ( $wgUser->isSysop() ) {
2526 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2527 '&action=delete' );
2528 $style = $this->getInternalLinkAttributes( $link, $delall );
2530 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2531 } else {
2532 $dlink = $del;
2534 } else {
2535 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
2536 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2537 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2538 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2539 urlencode( $img ) );
2540 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2541 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2542 } else {
2543 # Having live active links for non-logged in users
2544 # means that bots and spiders crawling our site can
2545 # inadvertently change content. Baaaad idea.
2546 $rlink = wfMsg( 'revertimg' );
2547 $dlink = $del;
2550 if ( 0 == $user ) {
2551 $userlink = $usertext;
2552 } else {
2553 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2554 ':'.$usertext, $usertext );
2556 $nbytes = wfMsg( 'nbytes', $size );
2557 $style = $this->getInternalLinkAttributes( $url, $datetime );
2559 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2560 . " . . {$userlink} ({$nbytes})";
2562 if ( '' != $description && '*' != $description ) {
2563 $sk=$wgUser->getSkin();
2564 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2566 $s .= "</li>\n";
2567 return $s;
2570 function tocIndent($level) {
2571 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2574 function tocUnindent($level) {
2575 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2578 # parameter level defines if we are on an indentation level
2579 function tocLine( $anchor, $tocline, $level ) {
2580 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2581 if($level) {
2582 return $link."\n";
2583 } else {
2584 return '<div class="tocline">'.$link."</div>\n";
2589 function tocTable($toc) {
2590 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2591 # try min-width & co when somebody gets a chance
2592 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2593 return
2594 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2595 '<b>'.wfMsg('toc').'</b>' .
2596 $hideline .
2597 '</td></tr><tr id="tocinside"><td>'."\n".
2598 $toc."</td></tr></table>\n";
2601 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2602 function editSectionScript( $section, $head ) {
2603 global $wgTitle, $wgRequest;
2604 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2605 return $head;
2607 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2608 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2611 function editSectionLink( $section ) {
2612 global $wgRequest;
2613 global $wgTitle, $wgUser, $wgLang;
2615 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2616 # Section edit links would be out of sync on an old page.
2617 # But, if we're diffing to the current page, they'll be
2618 # correct.
2619 return '';
2622 $editurl = '&section='.$section;
2623 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2625 if( $wgLang->isRTL() ) {
2626 $farside = 'left';
2627 $nearside = 'right';
2628 } else {
2629 $farside = 'right';
2630 $nearside = 'left';
2632 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2636 // This function is called by EditPage.php and shows a bulletin board style
2637 // toolbar for common editing functions. It can be disabled in the user preferences.
2638 // The necsesary JavaScript code can be found in style/wikibits.js.
2639 function getEditToolbar() {
2640 global $wgStylePath, $wgLang, $wgMimeType;
2642 // toolarray an array of arrays which each include the filename of
2643 // the button image (without path), the opening tag, the closing tag,
2644 // and optionally a sample text that is inserted between the two when no
2645 // selection is highlighted.
2646 // The tip text is shown when the user moves the mouse over the button.
2648 // Already here are accesskeys (key), which are not used yet until someone
2649 // can figure out a way to make them work in IE. However, we should make
2650 // sure these keys are not defined on the edit page.
2651 $toolarray=array(
2652 array( 'image'=>'button_bold.png',
2653 'open'=>"\'\'\'",
2654 'close'=>"\'\'\'",
2655 'sample'=>wfMsg('bold_sample'),
2656 'tip'=>wfMsg('bold_tip'),
2657 'key'=>'B'
2659 array( "image"=>"button_italic.png",
2660 "open"=>"\'\'",
2661 "close"=>"\'\'",
2662 "sample"=>wfMsg("italic_sample"),
2663 "tip"=>wfMsg("italic_tip"),
2664 "key"=>"I"
2666 array( "image"=>"button_link.png",
2667 "open"=>"[[",
2668 "close"=>"]]",
2669 "sample"=>wfMsg("link_sample"),
2670 "tip"=>wfMsg("link_tip"),
2671 "key"=>"L"
2673 array( "image"=>"button_extlink.png",
2674 "open"=>"[",
2675 "close"=>"]",
2676 "sample"=>wfMsg("extlink_sample"),
2677 "tip"=>wfMsg("extlink_tip"),
2678 "key"=>"X"
2680 array( "image"=>"button_headline.png",
2681 "open"=>"\\n== ",
2682 "close"=>" ==\\n",
2683 "sample"=>wfMsg("headline_sample"),
2684 "tip"=>wfMsg("headline_tip"),
2685 "key"=>"H"
2687 array( "image"=>"button_image.png",
2688 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2689 "close"=>"]]",
2690 "sample"=>wfMsg("image_sample"),
2691 "tip"=>wfMsg("image_tip"),
2692 "key"=>"D"
2694 array( "image"=>"button_media.png",
2695 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2696 "close"=>"]]",
2697 "sample"=>wfMsg("media_sample"),
2698 "tip"=>wfMsg("media_tip"),
2699 "key"=>"M"
2701 array( "image"=>"button_math.png",
2702 "open"=>"\\<math\\>",
2703 "close"=>"\\</math\\>",
2704 "sample"=>wfMsg("math_sample"),
2705 "tip"=>wfMsg("math_tip"),
2706 "key"=>"C"
2708 array( "image"=>"button_nowiki.png",
2709 "open"=>"\\<nowiki\\>",
2710 "close"=>"\\</nowiki\\>",
2711 "sample"=>wfMsg("nowiki_sample"),
2712 "tip"=>wfMsg("nowiki_tip"),
2713 "key"=>"N"
2715 array( "image"=>"button_sig.png",
2716 "open"=>"--~~~~",
2717 "close"=>"",
2718 "sample"=>"",
2719 "tip"=>wfMsg("sig_tip"),
2720 "key"=>"Y"
2722 array( "image"=>"button_hr.png",
2723 "open"=>"\\n----\\n",
2724 "close"=>"",
2725 "sample"=>"",
2726 "tip"=>wfMsg("hr_tip"),
2727 "key"=>"R"
2730 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2732 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2733 foreach($toolarray as $tool) {
2735 $image=$wgStylePath.'/images/'.$tool['image'];
2736 $open=$tool['open'];
2737 $close=$tool['close'];
2738 $sample = addslashes( $tool['sample'] );
2740 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2741 // Older browsers show a "speedtip" type message only for ALT.
2742 // Ideally these should be different, realistically they
2743 // probably don't need to be.
2744 $tip = addslashes( $tool['tip'] );
2746 #$key = $tool["key"];
2748 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2751 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2752 $toolbar.="document.writeln(\"</div>\");\n";
2754 $toolbar.="/*]]>*/\n</script>";
2755 return $toolbar;