The last checkin changed 'copyrightwarning' in a way that broke if the
[mediawiki.git] / includes / Skin.php
blobdc697349a3ec4de353e8cb75585e991bb8ba2c23
1 <?php
3 # This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
4 if( defined( "MEDIAWIKI" ) ) {
6 # See skin.doc
8 require_once( 'Feed.php' ); // should not be called if the actual page isn't feed enabled
9 require_once( 'Image.php' );
11 # These are the INTERNAL names, which get mapped
12 # directly to class names. For display purposes, the
13 # Language class has internationalized names
15 /* private */ $wgValidSkinNames = array(
16 'standard' => 'Standard',
17 'nostalgia' => 'Nostalgia',
18 'cologneblue' => 'CologneBlue'
20 if( $wgUsePHPTal ) {
21 #$wgValidSkinNames[] = 'PHPTal';
22 #$wgValidSkinNames['davinci'] = 'DaVinci';
23 #$wgValidSkinNames['mono'] = 'Mono';
24 $wgValidSkinNames['monobook'] = 'MonoBook';
25 $wgValidSkinNames['myskin'] = 'MySkin';
26 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
27 $wgValidSkinNames['chick'] = 'Chick';
30 require_once( 'RecentChange.php' );
32 class RCCacheEntry extends RecentChange
34 var $secureName, $link;
35 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
36 var $userlink, $timestamp, $watched;
38 function newFromParent( $rc )
40 $rc2 = new RCCacheEntry;
41 $rc2->mAttribs = $rc->mAttribs;
42 $rc2->mExtra = $rc->mExtra;
43 return $rc2;
45 } ;
47 class Skin {
49 /* private */ var $lastdate, $lastline;
50 var $linktrail ; # linktrail regexp
51 var $rc_cache ; # Cache for Enhanced Recent Changes
52 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
53 var $rcMoveIndex;
54 var $postParseLinkColour = true;
56 function Skin()
58 global $wgUseOldExistenceCheck;
59 $postParseLinkColour = !$wgUseOldExistenceCheck;
60 $this->linktrail = wfMsg('linktrail');
63 function getSkinNames()
65 global $wgValidSkinNames;
66 return $wgValidSkinNames;
69 function getStylesheet()
71 return 'wikistandard.css';
73 function getSkinName() {
74 return "standard";
77 # Get/set accessor for delayed link colouring
78 function postParseLinkColour( $setting = NULL ) {
79 return wfSetVar( $this->postParseLinkColour, $setting );
82 function qbSetting()
84 global $wgOut, $wgUser;
86 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
87 $q = $wgUser->getOption( 'quickbar' );
88 if ( '' == $q ) { $q = 0; }
89 return $q;
92 function initPage( &$out )
94 $fname = 'Skin::initPage';
95 wfProfileIn( $fname );
97 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
99 $this->addMetadataLinks($out);
101 wfProfileOut( $fname );
104 function addMetadataLinks( &$out ) {
105 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
106 global $wgRightsPage, $wgRightsUrl;
108 if( $out->isArticleRelated() ) {
109 # note: buggy CC software only reads first "meta" link
110 if( $wgEnableCreativeCommonsRdf ) {
111 $out->addMetadataLink( array(
112 'title' => 'Creative Commons',
113 'type' => 'application/rdf+xml',
114 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
116 if( $wgEnableDublinCoreRdf ) {
117 $out->addMetadataLink( array(
118 'title' => 'Dublin Core',
119 'type' => 'application/rdf+xml',
120 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
123 $copyright = '';
124 if( $wgRightsPage ) {
125 $copy = Title::newFromText( $wgRightsPage );
126 if( $copy ) {
127 $copyright = $copy->getLocalURL();
130 if( !$copyright && $wgRightsUrl ) {
131 $copyright = $wgRightsUrl;
133 if( $copyright ) {
134 $out->addLink( array(
135 'rel' => 'copyright',
136 'href' => $copyright ) );
140 function outputPage( &$out ) {
141 global $wgDebugComments;
143 wfProfileIn( 'Skin::outputPage' );
144 $this->initPage( $out );
145 $out->out( $out->headElement() );
147 $out->out( "\n<body" );
148 $ops = $this->getBodyOptions();
149 foreach ( $ops as $name => $val ) {
150 $out->out( " $name='$val'" );
152 $out->out( ">\n" );
153 if ( $wgDebugComments ) {
154 $out->out( "<!-- Wiki debugging output:\n" .
155 $out->mDebugtext . "-->\n" );
157 $out->out( $this->beforeContent() );
159 $out->out( $out->mBodytext . "\n" );
161 $out->out( $this->afterContent() );
163 wfProfileClose();
164 $out->out( $out->reportTime() );
166 $out->out( "\n</body></html>" );
169 function getHeadScripts() {
170 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
171 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
172 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
173 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
174 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
175 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
177 return $r;
180 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
181 function getUserStylesheet() {
182 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
183 $sheet = $this->getStylesheet();
184 $action = $wgRequest->getText('action');
185 $s = "@import \"$wgStylePath/$sheet\";\n";
186 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
187 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
188 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
189 $s .= $wgRequest->getText('wpTextbox1');
190 } else {
191 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
192 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
195 $s .= $this->doGetUserStyles();
196 return $s."\n";
198 # placeholder, returns generated js in monobook
199 function getUserJs() {
200 return;
203 function getUserStyles()
205 global $wgOut, $wgStylePath, $wgLang;
206 $s = "<style type='text/css'>\n";
207 $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
208 $s .= $this->getUserStylesheet();
209 $s .= "/*]]>*/ /* */\n";
210 $s .= "</style>\n";
211 return $s;
214 function doGetUserStyles()
216 global $wgUser, $wgLang;
218 $csspage = $wgLang->getNsText( NS_MEDIAWIKI ) . ":" . $this->getSkinName() . ".css";
219 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
221 if ( 1 == $wgUser->getOption( 'underline' ) ) {
222 # Don't override browser settings
223 } else {
224 # CHECK MERGE @@@
225 # Force no underline
226 $s .= "a { text-decoration: none; }\n";
228 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
229 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
231 if ( 1 == $wgUser->getOption( 'justify' ) ) {
232 $s .= "#article { text-align: justify; }\n";
234 return $s;
237 function getBodyOptions()
239 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
241 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
243 if ( 0 != $wgTitle->getNamespace() ) {
244 $a = array( 'bgcolor' => '#ffffec' );
246 else $a = array( 'bgcolor' => '#FFFFFF' );
247 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
248 (!$wgTitle->isProtected() || $wgUser->isSysop()) ) {
249 $t = wfMsg( 'editthispage' );
250 $oid = $red = '';
251 if ( !empty($redirect) ) {
252 $red = "&redirect={$redirect}";
254 if ( !empty($oldid) && ! isset( $diff ) ) {
255 $oid = "&oldid={$oldid}";
257 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
258 $s = 'document.location = "' .$s .'";';
259 $a += array ('ondblclick' => $s);
262 $a['onload'] = $wgOut->getOnloadHandler();
263 return $a;
266 function getExternalLinkAttributes( $link, $text, $class='' )
268 global $wgUser, $wgOut, $wgLang;
270 $link = urldecode( $link );
271 $link = $wgLang->checkTitleEncoding( $link );
272 $link = str_replace( '_', ' ', $link );
273 $link = htmlspecialchars( $link );
275 $r = ($class != '') ? " class='$class'" : " class='external'";
277 if ( 1 == $wgUser->getOption( 'hover' ) ) {
278 $r .= " title=\"{$link}\"";
280 return $r;
283 function getInternalLinkAttributes( $link, $text, $broken = false )
285 global $wgUser, $wgOut;
287 $link = urldecode( $link );
288 $link = str_replace( '_', ' ', $link );
289 $link = htmlspecialchars( $link );
291 if ( $broken == 'stub' ) {
292 $r = ' class="stub"';
293 } else if ( $broken == 'yes' ) {
294 $r = ' class="new"';
295 } else {
296 $r = '';
299 if ( 1 == $wgUser->getOption( 'hover' ) ) {
300 $r .= " title=\"{$link}\"";
302 return $r;
305 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
307 global $wgUser, $wgOut;
309 if ( $broken == 'stub' ) {
310 $r = ' class="stub"';
311 } else if ( $broken == 'yes' ) {
312 $r = ' class="new"';
313 } else {
314 $r = '';
317 if ( 1 == $wgUser->getOption( 'hover' ) ) {
318 $r .= ' title ="' . $nt->getEscapedText() . '"';
320 return $r;
323 function getLogo()
325 global $wgLogo;
326 return $wgLogo;
329 # This will be called immediately after the <body> tag. Split into
330 # two functions to make it easier to subclass.
332 function beforeContent()
334 global $wgUser, $wgOut;
336 return $this->doBeforeContent();
339 function doBeforeContent()
341 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
342 $fname = 'Skin::doBeforeContent';
343 wfProfileIn( $fname );
345 $s = '';
346 $qb = $this->qbSetting();
348 if( $langlinks = $this->otherLanguages() ) {
349 $rows = 2;
350 $borderhack = '';
351 } else {
352 $rows = 1;
353 $langlinks = false;
354 $borderhack = 'class="top"';
357 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
358 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
360 $shove = ($qb != 0);
361 $left = ($qb == 1 || $qb == 3);
362 if($wgLang->isRTL()) $left = !$left;
364 if ( !$shove ) {
365 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
366 $this->logoText() . '</td>';
367 } elseif( $left ) {
368 $s .= $this->getQuickbarCompensator( $rows );
370 $l = $wgLang->isRTL() ? 'right' : 'left';
371 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
373 $s .= $this->topLinks() ;
374 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
376 $r = $wgLang->isRTL() ? "left" : "right";
377 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
378 $s .= $this->nameAndLogin();
379 $s .= "\n<br />" . $this->searchForm() . "</td>";
381 if ( $langlinks ) {
382 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
385 if ( $shove && !$left ) { # Right
386 $s .= $this->getQuickbarCompensator( $rows );
388 $s .= "</tr>\n</table>\n</div>\n";
389 $s .= "\n<div id='article'>\n";
391 if( $wgSiteNotice ) {
392 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
394 $s .= $this->pageTitle();
395 $s .= $this->pageSubtitle() ;
396 $s .= $this->getCategories();
397 wfProfileOut( $fname );
398 return $s;
401 function getCategoryLinks () {
402 global $wgOut, $wgTitle, $wgUser, $wgParser;
403 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
405 if( !$wgUseCategoryMagic ) return '' ;
406 if( count( $wgOut->mCategoryLinks ) == 0 ) return '';
408 # Taken out so that they will be displayed in previews -- TS
409 #if( !$wgOut->isArticle() ) return '';
411 $t = implode ( ' | ' , $wgOut->mCategoryLinks ) ;
412 $s = $this->makeKnownLink( 'Special:Categories',
413 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
414 . ': ' . $t;
416 if($wgUseCategoryBrowser) {
417 $s .= '<br/><hr/>';
418 $catstack = array();
419 $s.= $wgTitle->getAllParentCategories($catstack);
422 return $s;
425 function getCategories() {
426 $catlinks=$this->getCategoryLinks();
427 if(!empty($catlinks)) {
428 return "<p class='catlinks'>{$catlinks}</p>";
432 function getQuickbarCompensator( $rows = 1 )
434 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
437 # This gets called immediately before the </body> tag.
439 function afterContent()
441 global $wgUser, $wgOut, $wgServer;
442 global $wgTitle, $wgLang;
444 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
445 return $printfooter . $this->doAfterContent();
448 function printSource() {
449 global $wgTitle;
450 $url = htmlspecialchars( $wgTitle->getFullURL() );
451 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
454 function printFooter() {
455 return "<p>" . $this->printSource() .
456 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
459 function doAfterContent()
461 global $wgUser, $wgOut, $wgLang;
462 $fname = 'Skin::doAfterContent';
463 wfProfileIn( $fname );
464 wfProfileIn( $fname.'-1' );
466 $s = "\n</div><br style=\"clear:both\" />\n";
467 $s .= "\n<div id='footer'>";
468 $s .= '<table border="0" cellspacing="0"><tr>';
470 wfProfileOut( $fname.'-1' );
471 wfProfileIn( $fname.'-2' );
473 $qb = $this->qbSetting();
474 $shove = ($qb != 0);
475 $left = ($qb == 1 || $qb == 3);
476 if($wgLang->isRTL()) $left = !$left;
478 if ( $shove && $left ) { # Left
479 $s .= $this->getQuickbarCompensator();
481 wfProfileOut( $fname.'-2' );
482 wfProfileIn( $fname.'-3' );
483 $l = $wgLang->isRTL() ? 'right' : 'left';
484 $s .= "<td class='bottom' align='$l' valign='top'>";
486 $s .= $this->bottomLinks();
487 $s .= "\n<br />" . $this->mainPageLink()
488 . ' | ' . $this->aboutLink()
489 . ' | ' . $this->specialLink( 'recentchanges' )
490 . ' | ' . $this->searchForm()
491 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
493 $s .= "</td>";
494 if ( $shove && !$left ) { # Right
495 $s .= $this->getQuickbarCompensator();
497 $s .= "</tr></table>\n</div>\n</div>\n";
499 wfProfileOut( $fname.'-3' );
500 wfProfileIn( $fname.'-4' );
501 if ( 0 != $qb ) { $s .= $this->quickBar(); }
502 wfProfileOut( $fname.'-4' );
503 wfProfileOut( $fname );
504 return $s;
507 function pageTitleLinks()
509 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
511 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
512 $action = $wgRequest->getText( 'action' );
514 $s = $this->printableLink();
515 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
517 if ( $wgOut->isArticleRelated() ) {
518 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
519 $name = $wgTitle->getDBkey();
520 $link = htmlspecialchars( Image::wfImageUrl( $name ) );
521 $style = $this->getInternalLinkAttributes( $link, $name );
522 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
524 # This will show the "Approve" link if $wgUseApproval=true;
525 if ( isset ( $wgUseApproval ) && $wgUseApproval )
527 $t = $wgTitle->getDBkey();
528 $name = 'Approve this article' ;
529 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
530 #htmlspecialchars( wfImageUrl( $name ) );
531 $style = $this->getExternalLinkAttributes( $link, $name );
532 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
535 if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) {
536 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
537 wfMsg( 'currentrev' ) );
540 if ( $wgUser->getNewtalk() ) {
541 # do not show "You have new messages" text when we are viewing our
542 # own talk page
544 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
545 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
546 $n =$wgUser->getName();
547 $tl = $this->makeKnownLink( $wgLang->getNsText(
548 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
549 wfMsg('newmessageslink') );
550 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
554 $undelete = $this->getUndeleteLink();
555 if( !empty( $undelete ) ) {
556 $s .= ' | '.$undelete;
558 return $s;
561 function getUndeleteLink() {
562 global $wgUser, $wgTitle, $wgLang, $action;
563 if( $wgUser->isSysop() &&
564 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
565 ($n = $wgTitle->isDeleted() ) ) {
566 return wfMsg( 'thisisdeleted',
567 $this->makeKnownLink(
568 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
569 wfMsg( 'restorelink', $n ) ) );
571 return '';
574 function printableLink()
576 global $wgOut, $wgFeedClasses, $wgRequest;
578 $baseurl = $_SERVER['REQUEST_URI'];
579 if( strpos( '?', $baseurl ) == false ) {
580 $baseurl .= '?';
581 } else {
582 $baseurl .= '&';
584 $baseurl = htmlspecialchars( $baseurl );
585 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
587 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
588 if( $wgOut->isSyndicated() ) {
589 foreach( $wgFeedClasses as $format => $class ) {
590 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
591 $s .= " | <a href=\"$feedurl\">{$format}</a>";
594 return $s;
597 function pageTitle()
599 global $wgOut, $wgTitle, $wgUser;
601 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
602 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
603 return $s;
606 function pageSubtitle()
608 global $wgOut;
610 $sub = $wgOut->getSubtitle();
611 if ( '' == $sub ) {
612 global $wgExtraSubtitle;
613 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
615 $subpages = $this->subPageSubtitle();
616 $sub .= !empty($subpages)?"</p><p class='subpages'>$subpages":'';
617 $s = "<p class='subtitle'>{$sub}</p>\n";
618 return $s;
621 function subPageSubtitle()
623 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
624 $subpages = '';
625 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
626 $ptext=$wgTitle->getPrefixedText();
627 if(preg_match('/\//',$ptext)) {
628 $links = explode('/',$ptext);
629 $c = 0;
630 $growinglink = '';
631 foreach($links as $link) {
632 $c++;
633 if ($c<count($links)) {
634 $growinglink .= $link;
635 $getlink = $this->makeLink( $growinglink, $link );
636 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
637 if ($c>1) {
638 $subpages .= ' | ';
639 } else {
640 $subpages .= '&lt; ';
642 $subpages .= $getlink;
643 $growinglink .= '/';
648 return $subpages;
651 function nameAndLogin()
653 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
655 $li = $wgLang->specialPage( 'Userlogin' );
656 $lo = $wgLang->specialPage( 'Userlogout' );
658 $s = '';
659 if ( 0 == $wgUser->getID() ) {
660 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
661 $n = $wgIP;
663 $tl = $this->makeKnownLink( $wgLang->getNsText(
664 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
665 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
667 $s .= $n . ' ('.$tl.')';
668 } else {
669 $s .= wfMsg('notloggedin');
672 $rt = $wgTitle->getPrefixedURL();
673 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
674 $q = '';
675 } else { $q = "returnto={$rt}"; }
677 $s .= "\n<br />" . $this->makeKnownLink( $li,
678 wfMsg( 'login' ), $q );
679 } else {
680 $n = $wgUser->getName();
681 $rt = $wgTitle->getPrefixedURL();
682 $tl = $this->makeKnownLink( $wgLang->getNsText(
683 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
684 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
686 $tl = " ({$tl})";
688 $s .= $this->makeKnownLink( $wgLang->getNsText(
689 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
690 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
691 "returnto={$rt}" ) . ' | ' .
692 $this->specialLink( 'preferences' );
694 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
695 wfMsg( 'help' ) );
697 return $s;
700 function getSearchLink() {
701 $searchPage =& Title::makeTitle( NS_SPECIAL, 'Search' );
702 return $searchPage->getLocalURL();
705 function escapeSearchLink() {
706 return htmlspecialchars( $this->getSearchLink() );
709 function searchForm()
711 global $wgRequest;
712 $search = $wgRequest->getText( 'search' );
714 $s = '<form name="search" class="inline" method="post" action="'
715 . $this->escapeSearchLink() . "\">\n"
716 . '<input type="text" name="search" size="19" value="'
717 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
718 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" />&nbsp;'
719 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
721 return $s;
724 function topLinks()
726 global $wgOut;
727 $sep = " |\n";
729 $s = $this->mainPageLink() . $sep
730 . $this->specialLink( 'recentchanges' );
732 if ( $wgOut->isArticleRelated() ) {
733 $s .= $sep . $this->editThisPage()
734 . $sep . $this->historyLink();
736 # Many people don't like this dropdown box
737 #$s .= $sep . $this->specialPagesList();
739 return $s;
742 function bottomLinks()
744 global $wgOut, $wgUser, $wgTitle;
745 $sep = " |\n";
747 $s = '';
748 if ( $wgOut->isArticleRelated() ) {
749 $s .= '<strong>' . $this->editThisPage() . '</strong>';
750 if ( 0 != $wgUser->getID() ) {
751 $s .= $sep . $this->watchThisPage();
753 $s .= $sep . $this->talkLink()
754 . $sep . $this->historyLink()
755 . $sep . $this->whatLinksHere()
756 . $sep . $this->watchPageLinksLink();
758 if ( $wgTitle->getNamespace() == Namespace::getUser()
759 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
762 $id=User::idFromName($wgTitle->getText());
763 $ip=User::isIP($wgTitle->getText());
765 if($id || $ip) { # both anons and non-anons have contri list
766 $s .= $sep . $this->userContribsLink();
768 if ( 0 != $wgUser->getID() ) { # show only to signed in users
769 if($id) { # can only email non-anons
770 $s .= $sep . $this->emailUserLink();
774 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
775 $s .= "\n<br />" . $this->deleteThisPage() .
776 $sep . $this->protectThisPage() .
777 $sep . $this->moveThisPage();
779 $s .= "<br />\n" . $this->otherLanguages();
781 return $s;
784 function pageStats()
786 global $wgOut, $wgLang, $wgArticle, $wgRequest;
787 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
789 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
790 if ( ! $wgOut->isArticle() ) { return ''; }
791 if ( isset( $oldid ) || isset( $diff ) ) { return ''; }
792 if ( 0 == $wgArticle->getID() ) { return ''; }
794 $s = '';
795 if ( !$wgDisableCounters ) {
796 $count = $wgLang->formatNum( $wgArticle->getCount() );
797 if ( $count ) {
798 $s = wfMsg( 'viewcount', $count );
802 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
803 require_once("Credits.php");
804 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
805 } else {
806 $s .= $this->lastModified();
809 return $s . ' ' . $this->getCopyright();
812 function getCopyright() {
813 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
816 $oldid = $wgRequest->getVal( 'oldid' );
817 $diff = $wgRequest->getVal( 'diff' );
819 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
820 $msg = 'history_copyright';
821 } else {
822 $msg = 'copyright';
825 $out = '';
826 if( $wgRightsPage ) {
827 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
828 } elseif( $wgRightsUrl ) {
829 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
830 } else {
831 # Give up now
832 return $out;
834 $out .= wfMsg( $msg, $link );
835 return $out;
838 function getCopyrightIcon() {
839 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
840 $out = '';
841 if( $wgRightsIcon ) {
842 $icon = htmlspecialchars( $wgRightsIcon );
843 if( $wgRightsUrl ) {
844 $url = htmlspecialchars( $wgRightsUrl );
845 $out .= '<a href="'.$url.'">';
847 $text = htmlspecialchars( $wgRightsText );
848 $out .= "<img src=\"$icon\" alt='$text' />";
849 if( $wgRightsUrl ) {
850 $out .= '</a>';
853 return $out;
856 function getPoweredBy() {
857 global $wgStylePath;
858 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
859 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
860 return $img;
863 function lastModified()
865 global $wgLang, $wgArticle;
867 $timestamp = $wgArticle->getTimestamp();
868 if ( $timestamp ) {
869 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
870 $s = ' ' . wfMsg( 'lastmodified', $d );
871 } else {
872 $s = '';
874 return $s;
877 function logoText( $align = '' )
879 if ( '' != $align ) { $a = ' align="'.$align.'"'; }
880 else { $a = ''; }
882 $mp = wfMsg( 'mainpage' );
883 $titleObj = Title::newFromText( $mp );
884 $s = '<a href="' . $titleObj->escapeLocalURL()
885 . '"><img'.$a.' src="'
886 . $this->getLogo() . '" alt="' . "[{$mp}]\" /></a>";
887 return $s;
890 function quickBar()
892 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
893 global $wgDisableUploads, $wgRemoteUploads;
895 $fname = 'Skin::quickBar';
896 wfProfileIn( $fname );
898 $action = $wgRequest->getText( 'action' );
899 $wpPreview = $wgRequest->getBool( 'wpPreview' );
900 $tns=$wgTitle->getNamespace();
902 $s = "\n<div id='quickbar'>";
903 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
905 $sep = "\n<br />";
906 $s .= $this->mainPageLink()
907 . $sep . $this->specialLink( 'recentchanges' )
908 . $sep . $this->specialLink( 'randompage' );
909 if ($wgUser->getID()) {
910 $s.= $sep . $this->specialLink( 'watchlist' ) ;
911 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
912 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
915 // only show watchlist link if logged in
916 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
917 $s .= "\n<br /><hr class='sep' />";
918 $articleExists = $wgTitle->getArticleId();
919 if ( $wgOut->isArticle() || $action =='edit' || $action =='history' || $wpPreview) {
920 if($wgOut->isArticle()) {
921 $s .= '<strong>' . $this->editThisPage() . '</strong>';
922 } else { # backlink to the article in edit or history mode
923 if($articleExists){ # no backlink if no article
924 switch($tns) {
925 case 0:
926 $text = wfMsg('articlepage');
927 break;
928 case 1:
929 $text = wfMsg('viewtalkpage');
930 break;
931 case 2:
932 $text = wfMsg('userpage');
933 break;
934 case 3:
935 $text = wfMsg('viewtalkpage');
936 break;
937 case 4:
938 $text = wfMsg('wikipediapage');
939 break;
940 case 5:
941 $text = wfMsg('viewtalkpage');
942 break;
943 case 6:
944 $text = wfMsg('imagepage');
945 break;
946 case 7:
947 $text = wfMsg('viewtalkpage');
948 break;
949 default:
950 $text= wfMsg('articlepage');
953 $link = $wgTitle->getText();
954 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
955 $link = $nstext . ':' . $link ;
958 $s .= $this->makeLink( $link, $text );
959 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
960 # we just throw in a "New page" text to tell the user that he's in edit mode,
961 # and to avoid messing with the separator that is prepended to the next item
962 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
968 if( $tns%2 && $action!='edit' && !$wpPreview) {
969 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit&section=new');
973 watching could cause problems in edit mode:
974 if user edits article, then loads "watch this article" in background and then saves
975 article with "Watch this article" checkbox disabled, the article is transparently
976 unwatched. Therefore we do not show the "Watch this page" link in edit mode
978 if ( 0 != $wgUser->getID() && $articleExists) {
979 if($action!='edit' && $action != 'submit' )
981 $s .= $sep . $this->watchThisPage();
983 if ( $wgTitle->userCanEdit() )
984 $s .= $sep . $this->moveThisPage();
986 if ( $wgUser->isSysop() and $articleExists ) {
987 $s .= $sep . $this->deleteThisPage() .
988 $sep . $this->protectThisPage();
990 $s .= $sep . $this->talkLink();
991 if ($articleExists && $action !='history') {
992 $s .= $sep . $this->historyLink();
994 $s.=$sep . $this->whatLinksHere();
996 if($wgOut->isArticleRelated()) {
997 $s .= $sep . $this->watchPageLinksLink();
1000 if ( Namespace::getUser() == $wgTitle->getNamespace()
1001 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1004 $id=User::idFromName($wgTitle->getText());
1005 $ip=User::isIP($wgTitle->getText());
1007 if($id||$ip) {
1008 $s .= $sep . $this->userContribsLink();
1010 if ( 0 != $wgUser->getID() ) {
1011 if($id) { # can only email real users
1012 $s .= $sep . $this->emailUserLink();
1016 $s .= "\n<br /><hr class='sep' />";
1019 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
1020 $s .= $this->specialLink( 'upload' ) . $sep;
1022 $s .= $this->specialLink( 'specialpages' )
1023 . $sep . $this->bugReportsLink();
1025 global $wgSiteSupportPage;
1026 if( $wgSiteSupportPage ) {
1027 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1028 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1031 $s .= "\n<br /></div>\n";
1032 wfProfileOut( $fname );
1033 return $s;
1036 function specialPagesList()
1038 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1039 require_once('SpecialPage.php');
1040 $a = array();
1041 $pages = SpecialPage::getPages();
1043 foreach ( $pages[''] as $name => $page ) {
1044 $a[$name] = $page->getDescription();
1046 if ( $wgUser->isSysop() )
1048 foreach ( $pages['sysop'] as $name => $page ) {
1049 $a[$name] = $page->getDescription();
1052 if ( $wgUser->isDeveloper() )
1054 foreach ( $pages['developer'] as $name => $page ) {
1055 $a[$name] = $page->getDescription() ;
1058 $go = wfMsg( 'go' );
1059 $sp = wfMsg( 'specialpages' );
1060 $spp = $wgLang->specialPage( 'Specialpages' );
1062 $s = '<form id="specialpages" method="get" class="inline" ' .
1063 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1064 $s .= "<select name=\"wpDropdown\">\n";
1065 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1067 foreach ( $a as $name => $desc ) {
1068 $p = $wgLang->specialPage( $name );
1069 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1071 $s .= "</select>\n";
1072 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1073 $s .= "</form>\n";
1074 return $s;
1077 function mainPageLink()
1079 $mp = wfMsg( 'mainpage' );
1080 $s = $this->makeKnownLink( $mp, $mp );
1081 return $s;
1084 function copyrightLink()
1086 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1087 wfMsg( 'copyrightpagename' ) );
1088 return $s;
1091 function aboutLink()
1093 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1094 wfMsg( 'aboutwikipedia' ) );
1095 return $s;
1099 function disclaimerLink()
1101 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1102 wfMsg( 'disclaimers' ) );
1103 return $s;
1106 function editThisPage()
1108 global $wgOut, $wgTitle, $wgRequest;
1110 $oldid = $wgRequest->getVal( 'oldid' );
1111 $diff = $wgRequest->getVal( 'diff' );
1112 $redirect = $wgRequest->getVal( 'redirect' );
1114 if ( ! $wgOut->isArticleRelated() ) {
1115 $s = wfMsg( 'protectedpage' );
1116 } else {
1117 $n = $wgTitle->getPrefixedText();
1118 if ( $wgTitle->userCanEdit() ) {
1119 $t = wfMsg( 'editthispage' );
1120 } else {
1121 #$t = wfMsg( "protectedpage" );
1122 $t = wfMsg( 'viewsource' );
1124 $oid = $red = '';
1126 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1127 if ( $oldid && ! isset( $diff ) ) {
1128 $oid = "&oldid={$oldid}";
1130 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1132 return $s;
1135 function deleteThisPage()
1137 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1139 $diff = $wgRequest->getVal( 'diff' );
1140 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1141 $n = $wgTitle->getPrefixedText();
1142 $t = wfMsg( 'deletethispage' );
1144 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1145 } else {
1146 $s = '';
1148 return $s;
1151 function protectThisPage()
1153 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1155 $diff = $wgRequest->getVal( 'diff' );
1156 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1157 $n = $wgTitle->getPrefixedText();
1159 if ( $wgTitle->isProtected() ) {
1160 $t = wfMsg( 'unprotectthispage' );
1161 $q = 'action=unprotect';
1162 } else {
1163 $t = wfMsg( 'protectthispage' );
1164 $q = 'action=protect';
1166 $s = $this->makeKnownLink( $n, $t, $q );
1167 } else {
1168 $s = '';
1170 return $s;
1173 function watchThisPage()
1175 global $wgUser, $wgOut, $wgTitle;
1177 if ( $wgOut->isArticleRelated() ) {
1178 $n = $wgTitle->getPrefixedText();
1180 if ( $wgTitle->userIsWatching() ) {
1181 $t = wfMsg( 'unwatchthispage' );
1182 $q = 'action=unwatch';
1183 } else {
1184 $t = wfMsg( 'watchthispage' );
1185 $q = 'action=watch';
1187 $s = $this->makeKnownLink( $n, $t, $q );
1188 } else {
1189 $s = wfMsg( 'notanarticle' );
1191 return $s;
1194 function moveThisPage()
1196 global $wgTitle, $wgLang;
1198 if ( $wgTitle->userCanEdit() ) {
1199 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1200 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1201 } // no message if page is protected - would be redundant
1202 return $s;
1205 function historyLink()
1207 global $wgTitle;
1209 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1210 wfMsg( 'history' ), 'action=history' );
1211 return $s;
1214 function whatLinksHere()
1216 global $wgTitle, $wgLang;
1218 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1219 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1220 return $s;
1223 function userContribsLink()
1225 global $wgTitle, $wgLang;
1227 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1228 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1229 return $s;
1232 function emailUserLink()
1234 global $wgTitle, $wgLang;
1236 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1237 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1238 return $s;
1241 function watchPageLinksLink()
1243 global $wgOut, $wgTitle, $wgLang;
1245 if ( ! $wgOut->isArticleRelated() ) {
1246 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1247 } else {
1248 $s = $this->makeKnownLink( $wgLang->specialPage(
1249 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1250 'target=' . $wgTitle->getPrefixedURL() );
1252 return $s;
1255 function otherLanguages()
1257 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1259 $a = $wgOut->getLanguageLinks();
1260 if ( 0 == count( $a ) ) {
1261 if ( !$wgUseNewInterlanguage ) return '';
1262 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1263 if ( $ns != 0 AND $ns != 1 ) return '' ;
1264 $pn = 'Intl' ;
1265 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1266 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1267 wfMsg( 'intl' ) , $x );
1270 if ( !$wgUseNewInterlanguage ) {
1271 $s = wfMsg( 'otherlanguages' ) . ': ';
1272 } else {
1273 global $wgLanguageCode ;
1274 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1275 $x .= '&xl='.$wgLanguageCode ;
1276 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1277 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1280 $s = wfMsg( 'otherlanguages' ) . ': ';
1281 $first = true;
1282 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1283 foreach( $a as $l ) {
1284 if ( ! $first ) { $s .= ' | '; }
1285 $first = false;
1287 $nt = Title::newFromText( $l );
1288 $url = $nt->getFullURL();
1289 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1291 if ( '' == $text ) { $text = $l; }
1292 $style = $this->getExternalLinkAttributes( $l, $text );
1293 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1295 if($wgLang->isRTL()) $s .= '</span>';
1296 return $s;
1299 function bugReportsLink()
1301 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1302 wfMsg( 'bugreports' ) );
1303 return $s;
1306 function dateLink()
1308 global $wgLinkCache;
1309 $t1 = Title::newFromText( gmdate( 'F j' ) );
1310 $t2 = Title::newFromText( gmdate( 'Y' ) );
1312 $wgLinkCache->suspend();
1313 $id = $t1->getArticleID();
1314 $wgLinkCache->resume();
1316 if ( 0 == $id ) {
1317 $s = $this->makeBrokenLink( $t1->getText() );
1318 } else {
1319 $s = $this->makeKnownLink( $t1->getText() );
1321 $s .= ', ';
1323 $wgLinkCache->suspend();
1324 $id = $t2->getArticleID();
1325 $wgLinkCache->resume();
1327 if ( 0 == $id ) {
1328 $s .= $this->makeBrokenLink( $t2->getText() );
1329 } else {
1330 $s .= $this->makeKnownLink( $t2->getText() );
1332 return $s;
1335 function talkLink()
1337 global $wgLang, $wgTitle, $wgLinkCache;
1339 $tns = $wgTitle->getNamespace();
1340 if ( -1 == $tns ) { return ''; }
1342 $pn = $wgTitle->getText();
1343 $tp = wfMsg( 'talkpage' );
1344 if ( Namespace::isTalk( $tns ) ) {
1345 $lns = Namespace::getSubject( $tns );
1346 switch($tns) {
1347 case 1:
1348 $text = wfMsg('articlepage');
1349 break;
1350 case 3:
1351 $text = wfMsg('userpage');
1352 break;
1353 case 5:
1354 $text = wfMsg('wikipediapage');
1355 break;
1356 case 7:
1357 $text = wfMsg('imagepage');
1358 break;
1359 default:
1360 $text= wfMsg('articlepage');
1362 } else {
1364 $lns = Namespace::getTalk( $tns );
1365 $text=$tp;
1367 $n = $wgLang->getNsText( $lns );
1368 if ( '' == $n ) { $link = $pn; }
1369 else { $link = $n.':'.$pn; }
1371 $wgLinkCache->suspend();
1372 $s = $this->makeLink( $link, $text );
1373 $wgLinkCache->resume();
1375 return $s;
1378 function commentLink()
1380 global $wgLang, $wgTitle, $wgLinkCache;
1382 $tns = $wgTitle->getNamespace();
1383 if ( -1 == $tns ) { return ''; }
1385 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1387 # assert Namespace::isTalk( $lns )
1389 $n = $wgLang->getNsText( $lns );
1390 $pn = $wgTitle->getText();
1392 $link = $n.':'.$pn;
1394 $wgLinkCache->suspend();
1395 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit&section=new');
1396 $wgLinkCache->resume();
1398 return $s;
1401 # After all the page content is transformed into HTML, it makes
1402 # a final pass through here for things like table backgrounds.
1404 function transformContent( $text )
1406 return $text;
1409 # Note: This function MUST call getArticleID() on the link,
1410 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1412 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1413 wfProfileIn( 'Skin::makeLink' );
1414 $nt = Title::newFromText( $title );
1415 if ($nt) {
1416 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1417 } else {
1418 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1419 $result = $text == "" ? $title : $text;
1422 wfProfileOut( 'Skin::makeLink' );
1423 return $result;
1426 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1427 $nt = Title::newFromText( $title );
1428 if ($nt) {
1429 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1430 } else {
1431 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1432 return $text == '' ? $title : $text;
1436 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1437 $nt = Title::newFromText( $title );
1438 if ($nt) {
1439 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1440 } else {
1441 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1442 return $text == '' ? $title : $text;
1446 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1447 $nt = Title::newFromText( $title );
1448 if ($nt) {
1449 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1450 } else {
1451 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1452 return $text == '' ? $title : $text;
1456 # Pass a title object, not a title string
1457 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1459 global $wgOut, $wgUser;
1460 $fname = 'Skin::makeLinkObj';
1462 # Fail gracefully
1463 if ( ! isset($nt) )
1464 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1466 if ( $nt->isExternal() ) {
1467 $u = $nt->getFullURL();
1468 $link = $nt->getPrefixedURL();
1469 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1470 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1472 $inside = '';
1473 if ( '' != $trail ) {
1474 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1475 $inside = $m[1];
1476 $trail = $m[2];
1479 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1480 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1481 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1482 } elseif ( ( -1 == $nt->getNamespace() ) ||
1483 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1484 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1485 } else {
1486 if ( $this->postParseLinkColour() ) {
1487 $inside = '';
1488 if ( '' != $trail ) {
1489 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1490 $inside = $m[1];
1491 $trail = $m[2];
1495 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1496 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1497 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1498 } else {
1499 # Work out link colour immediately
1500 $aid = $nt->getArticleID() ;
1501 if ( 0 == $aid ) {
1502 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1503 } else {
1504 $threshold = $wgUser->getOption('stubthreshold') ;
1505 if ( $threshold > 0 ) {
1506 $dbr =& wfGetDB( DB_SLAVE );
1507 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1508 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1509 if ( $s !== false ) {
1510 $size = $s->x;
1511 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1512 $size = $threshold*2 ; # Really big
1514 $dbr->freeResult( $res );
1515 } else {
1516 $size = $threshold*2 ; # Really big
1518 } else {
1519 $size = 1 ;
1521 if ( $size < $threshold ) {
1522 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1523 } else {
1524 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1529 return $retVal;
1532 # Pass a title object, not a title string
1533 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1535 global $wgOut, $wgTitle, $wgInputEncoding;
1537 $fname = 'Skin::makeKnownLinkObj';
1538 wfProfileIn( $fname );
1540 if ( !is_object( $nt ) ) {
1541 return $text;
1543 $link = $nt->getPrefixedURL();
1545 if ( '' == $link ) {
1546 $u = '';
1547 if ( '' == $text ) {
1548 $text = htmlspecialchars( $nt->getFragment() );
1550 } else {
1551 $u = $nt->escapeLocalURL( $query );
1553 if ( '' != $nt->getFragment() ) {
1554 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT, $wgInputEncoding ) );
1555 $replacearray = array(
1556 '%3A' => ':',
1557 '%' => '.'
1559 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1561 if ( '' == $text ) {
1562 $text = htmlspecialchars( $nt->getPrefixedText() );
1564 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1566 $inside = '';
1567 if ( '' != $trail ) {
1568 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1569 $inside = $m[1];
1570 $trail = $m[2];
1573 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1574 wfProfileOut( $fname );
1575 return $r;
1578 # Pass a title object, not a title string
1579 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1581 global $wgOut, $wgUser;
1583 # Fail gracefully
1584 if ( ! isset($nt) )
1585 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1587 $fname = 'Skin::makeBrokenLinkObj';
1588 wfProfileIn( $fname );
1590 if ( '' == $query ) {
1591 $q = 'action=edit';
1592 } else {
1593 $q = 'action=edit&'.$query;
1595 $u = $nt->escapeLocalURL( $q );
1597 if ( '' == $text ) {
1598 $text = htmlspecialchars( $nt->getPrefixedText() );
1600 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1602 $inside = '';
1603 if ( '' != $trail ) {
1604 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1605 $inside = $m[1];
1606 $trail = $m[2];
1609 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1610 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1611 } else {
1612 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1615 wfProfileOut( $fname );
1616 return $s;
1619 # Pass a title object, not a title string
1620 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1622 global $wgOut, $wgUser;
1624 $link = $nt->getPrefixedURL();
1626 $u = $nt->escapeLocalURL( $query );
1628 if ( '' == $text ) {
1629 $text = htmlspecialchars( $nt->getPrefixedText() );
1631 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1633 $inside = '';
1634 if ( '' != $trail ) {
1635 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1636 $inside = $m[1];
1637 $trail = $m[2];
1640 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1641 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1642 } else {
1643 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1645 return $s;
1648 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1650 $u = $nt->escapeLocalURL( $query );
1651 if ( '' == $text ) {
1652 $text = htmlspecialchars( $nt->getPrefixedText() );
1654 $inside = '';
1655 if ( '' != $trail ) {
1656 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1657 $inside = $m[1];
1658 $trail = $m[2];
1661 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1664 /* these are used extensively in SkinPHPTal, but also some other places */
1665 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1666 $title = Title::makeTitle( NS_SPECIAL, $name );
1667 $this->checkTitle($title, $name);
1668 return $title->getLocalURL( $urlaction );
1670 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1671 $title = Title::newFromText( $name );
1672 $title = $title->getTalkPage();
1673 $this->checkTitle($title, $name);
1674 return $title->getLocalURL( $urlaction );
1676 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1677 $title = Title::newFromText( $name );
1678 $title= $title->getSubjectPage();
1679 $this->checkTitle($title, $name);
1680 return $title->getLocalURL( $urlaction );
1682 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1683 $title = Title::newFromText( wfMsg($name) );
1684 $this->checkTitle($title, $name);
1685 return $title->getLocalURL( $urlaction );
1687 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1688 $title = Title::newFromText( $name );
1689 $this->checkTitle($title, $name);
1690 return $title->getLocalURL( $urlaction );
1692 # this can be passed the NS number as defined in Language.php
1693 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1694 $title = Title::makeTitle( $namespace, $name );
1695 $this->checkTitle($title, $name);
1696 return $title->getLocalURL( $urlaction );
1699 /* these return an array with the 'href' and boolean 'exists' */
1700 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1701 $title = Title::newFromText( $name );
1702 $this->checkTitle($title, $name);
1703 return array(
1704 'href' => $title->getLocalURL( $urlaction ),
1705 'exists' => $title->getArticleID() != 0?true:false
1708 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1709 $title = Title::newFromText( $name );
1710 $title = $title->getTalkPage();
1711 $this->checkTitle($title, $name);
1712 return array(
1713 'href' => $title->getLocalURL( $urlaction ),
1714 'exists' => $title->getArticleID() != 0?true:false
1717 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1718 $title = Title::newFromText( $name );
1719 $title= $title->getSubjectPage();
1720 $this->checkTitle($title, $name);
1721 return array(
1722 'href' => $title->getLocalURL( $urlaction ),
1723 'exists' => $title->getArticleID() != 0?true:false
1726 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1727 $title = Title::newFromText( wfMsg($name) );
1728 $this->checkTitle($title, $name);
1729 return array(
1730 'href' => $title->getLocalURL( $urlaction ),
1731 'exists' => $title->getArticleID() != 0?true:false
1735 # make sure we have some title to operate on
1736 /*static*/ function checkTitle ( &$title, &$name ) {
1737 if(!is_object($title)) {
1738 $title = Title::newFromText( $name );
1739 if(!is_object($title)) {
1740 $title = Title::newFromText( '--error: link target missing--' );
1745 function fnamePart( $url )
1747 $basename = strrchr( $url, '/' );
1748 if ( false === $basename ) {
1749 $basename = $url;
1750 } else {
1751 $basename = substr( $basename, 1 );
1753 return htmlspecialchars( $basename );
1756 function makeImage( $url, $alt = '' )
1758 global $wgOut;
1760 if ( '' == $alt ) {
1761 $alt = $this->fnamePart( $url );
1763 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1764 return $s;
1767 function makeImageLink( $name, $url, $alt = '' ) {
1768 $nt = Title::makeTitle( Namespace::getImage(), $name );
1769 return $this->makeImageLinkObj( $nt, $alt );
1772 function makeImageLinkObj( $nt, $alt = '' ) {
1773 global $wgLang, $wgUseImageResize;
1774 $img = Image::newFromTitle( $nt );
1775 $url = $img->getURL();
1777 $align = '';
1778 $prefix = $postfix = '';
1780 if ( $wgUseImageResize ) {
1781 # Check if the alt text is of the form "options|alt text"
1782 # Options are:
1783 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1784 # * left no resizing, just left align. label is used for alt= only
1785 # * right same, but right aligned
1786 # * none same, but not aligned
1787 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1788 # * center center the image
1789 # * framed Keep original image size, no magnify-button.
1791 $part = explode( '|', $alt);
1793 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1794 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1795 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1796 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1797 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1798 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1799 $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
1800 $alt = $part[count($part)-1];
1802 $height = $framed = $thumb = false;
1803 $manual_thumb = "" ;
1805 foreach( $part as $key => $val ) {
1806 $val_parts = explode ( "=" , $val , 2 ) ;
1807 $left_part = array_shift ( $val_parts ) ;
1808 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1809 $thumb=true;
1810 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1811 # use manually specified thumbnail
1812 $thumb=true;
1813 $manual_thumb = array_shift ( $val_parts ) ;
1814 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1815 # remember to set an alignment, don't render immediately
1816 $align = 'right';
1817 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1818 # remember to set an alignment, don't render immediately
1819 $align = 'left';
1820 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1821 # remember to set an alignment, don't render immediately
1822 $align = 'center';
1823 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1824 # remember to set an alignment, don't render immediately
1825 $align = 'none';
1826 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1827 # $match is the image width in pixels
1828 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1829 $width = intval( $m[1] );
1830 $height = intval( $m[2] );
1831 } else {
1832 $width = intval($match);
1834 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1835 $framed=true;
1838 if ( 'center' == $align )
1840 $prefix = '<span style="text-align: center">';
1841 $postfix = '</span>';
1842 $align = 'none';
1845 if ( $thumb || $framed ) {
1847 # Create a thumbnail. Alignment depends on language
1848 # writing direction, # right aligned for left-to-right-
1849 # languages ("Western languages"), left-aligned
1850 # for right-to-left-languages ("Semitic languages")
1852 # If thumbnail width has not been provided, it is set
1853 # here to 180 pixels
1854 if ( $align == '' ) {
1855 $align = $wgLang->isRTL() ? 'left' : 'right';
1857 if ( ! isset($width) ) {
1858 $width = 180;
1860 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1862 } elseif ( isset($width) ) {
1864 # Create a resized image, without the additional thumbnail
1865 # features
1867 if ( ( ! $height === false )
1868 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1869 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1870 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1871 $width = $img->getWidth() * $height / $img->getHeight();
1873 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1875 } # endif $wgUseImageResize
1877 if ( empty( $alt ) ) {
1878 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1880 $alt = htmlspecialchars( $alt );
1882 $u = $nt->escapeLocalURL();
1883 if ( $url == '' )
1885 $s = wfMsg( 'missingimage', $img->getName() );
1886 $s .= "<br>{$alt}<br>{$url}<br>\n";
1887 } else {
1888 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1889 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1891 if ( '' != $align ) {
1892 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1894 return str_replace("\n", ' ',$prefix.$s.$postfix);
1897 # Make HTML for a thumbnail including image, border and caption
1898 # $img is an Image object
1899 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1900 global $wgStylePath, $wgLang;
1901 # $image = Title::makeTitle( Namespace::getImage(), $name );
1902 $url = $img->getURL();
1904 #$label = htmlspecialchars( $label );
1905 $alt = preg_replace( '/<[^>]*>/', '', $label);
1906 $alt = htmlspecialchars( $alt );
1908 $width = $height = 0;
1909 if ( $img->exists() )
1911 $width = $img->getWidth();
1912 $height = $img->getHeight();
1914 if ( 0 == $width || 0 == $height )
1916 $width = $height = 200;
1918 if ( $boxwidth == 0 )
1920 $boxwidth = 200;
1922 if ( $framed )
1924 // Use image dimensions, don't scale
1925 $boxwidth = $width;
1926 $oboxwidth = $boxwidth + 2;
1927 $boxheight = $height;
1928 $thumbUrl = $url;
1929 } else {
1930 $h = intval( $height/($width/$boxwidth) );
1931 $oboxwidth = $boxwidth + 2;
1932 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1934 $boxwidth *= $boxheight/$h;
1935 } else {
1936 $boxheight = $h;
1938 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1941 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1943 $manual_title = Title::makeTitle( Namespace::getImage(), $manual_thumb ); #new Title ( $manual_thumb ) ;
1944 $manual_img = Image::newFromTitle( $manual_title );
1945 $thumbUrl = $manual_img->getURL();
1946 if ( $manual_img->exists() )
1948 $width = $manual_img->getWidth();
1949 $height = $manual_img->getHeight();
1950 $boxwidth = $width ;
1951 $boxheight = $height ;
1952 $oboxwidth = $boxwidth + 2 ;
1956 $u = $img->getEscapeLocalURL();
1958 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1959 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1960 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1962 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1963 if ( $thumbUrl == '' ) {
1964 $s .= wfMsg( 'missingimage', $img->getName() );
1965 $zoomicon = '';
1966 } else {
1967 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1968 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1969 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1970 if ( $framed ) {
1971 $zoomicon="";
1972 } else {
1973 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1974 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1975 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1976 'width="15" height="11" alt="'.$more.'" /></a></div>';
1979 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1980 return str_replace("\n", ' ', $s);
1983 function makeMediaLink( $name, $url, $alt = "" ) {
1984 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1985 return $this->makeMediaLinkObj( $nt, $alt );
1988 function makeMediaLinkObj( $nt, $alt = "" )
1990 if ( ! isset( $nt ) )
1992 ### HOTFIX. Instead of breaking, return empty string.
1993 $s = $alt;
1994 } else {
1995 $name = $nt->getDBKey();
1996 $url = Image::wfImageUrl( $name );
1997 if ( empty( $alt ) ) {
1998 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2001 $u = htmlspecialchars( $url );
2002 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2004 return $s;
2007 function specialLink( $name, $key = "" )
2009 global $wgLang;
2011 if ( '' == $key ) { $key = strtolower( $name ); }
2012 $pn = $wgLang->ucfirst( $name );
2013 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2014 wfMsg( $key ) );
2017 function makeExternalLink( $url, $text, $escape = true ) {
2018 $style = $this->getExternalLinkAttributes( $url, $text );
2019 $url = htmlspecialchars( $url );
2020 if( $escape ) {
2021 $text = htmlspecialchars( $text );
2023 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2026 # Called by history lists and recent changes
2029 # Returns text for the start of the tabular part of RC
2030 function beginRecentChangesList()
2032 $this->rc_cache = array() ;
2033 $this->rcMoveIndex = 0;
2034 $this->rcCacheIndex = 0 ;
2035 $this->lastdate = '';
2036 $this->rclistOpen = false;
2037 return '';
2040 function beginImageHistoryList()
2042 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2043 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2044 return $s;
2047 # Returns text for the end of RC
2048 # If enhanced RC is in use, returns pretty much all the text
2049 function endRecentChangesList()
2051 $s = $this->recentChangesBlock() ;
2052 if( $this->rclistOpen ) {
2053 $s .= "</ul>\n";
2055 return $s;
2058 # Enhanced RC ungrouped line
2059 function recentChangesBlockLine ( $rcObj )
2061 global $wgStylePath, $wgLang ;
2063 # Get rc_xxxx variables
2064 extract( $rcObj->mAttribs ) ;
2065 $curIdEq = 'curid='.$rc_cur_id;
2067 # Spacer image
2068 $r = '' ;
2070 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2071 $r .= '<tt>' ;
2073 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2074 $r .= '&nbsp;&nbsp;';
2075 } else {
2076 # M & N (minor & new)
2077 $M = wfMsg( 'minoreditletter' );
2078 $N = wfMsg( 'newpageletter' );
2080 if ( $rc_type == RC_NEW ) {
2081 $r .= $N ;
2082 } else {
2083 $r .= '&nbsp;' ;
2085 if ( $rc_minor ) {
2086 $r .= $M ;
2087 } else {
2088 $r .= '&nbsp;' ;
2092 # Timestamp
2093 $r .= ' '.$rcObj->timestamp.' ' ;
2094 $r .= '</tt>' ;
2096 # Article link
2097 $link = $rcObj->link ;
2098 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2099 $r .= $link ;
2101 # Diff
2102 $r .= ' (' ;
2103 $r .= $rcObj->difflink ;
2104 $r .= '; ' ;
2106 # Hist
2107 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2109 # User/talk
2110 $r .= ') . . '.$rcObj->userlink ;
2111 $r .= $rcObj->usertalklink ;
2113 # Comment
2114 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2115 $rc_comment=$this->formatComment($rc_comment);
2116 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2119 $r .= "<br />\n" ;
2120 return $r ;
2123 # Enhanced RC group
2124 function recentChangesBlockGroup ( $block )
2126 global $wgStylePath, $wgLang ;
2128 $r = '' ;
2129 $M = wfMsg( 'minoreditletter' );
2130 $N = wfMsg( 'newpageletter' );
2132 # Collate list of users
2133 $isnew = false ;
2134 $userlinks = array () ;
2135 foreach ( $block AS $rcObj ) {
2136 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2137 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2138 $u = $rcObj->userlink ;
2139 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2140 $userlinks[$u]++ ;
2143 # Sort the list and convert to text
2144 krsort ( $userlinks ) ;
2145 asort ( $userlinks ) ;
2146 $users = array () ;
2147 foreach ( $userlinks as $userlink => $count) {
2148 $text = $userlink ;
2149 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2150 array_push ( $users , $text ) ;
2152 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2154 # Arrow
2155 $rci = 'RCI'.$this->rcCacheIndex ;
2156 $rcl = 'RCL'.$this->rcCacheIndex ;
2157 $rcm = 'RCM'.$this->rcCacheIndex ;
2158 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2159 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2160 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2161 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2162 $r .= $tl ;
2164 # Main line
2165 # M/N
2166 $r .= '<tt>' ;
2167 if ( $isnew ) $r .= $N ;
2168 else $r .= '&nbsp;' ;
2169 $r .= '&nbsp;' ; # Minor
2171 # Timestamp
2172 $r .= ' '.$block[0]->timestamp.' ' ;
2173 $r .= '</tt>' ;
2175 # Article link
2176 $link = $block[0]->link ;
2177 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2178 $r .= $link ;
2180 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2181 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2182 # Changes
2183 $r .= ' ('.count($block).' ' ;
2184 if ( $isnew ) $r .= wfMsg('changes');
2185 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2186 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2187 $r .= '; ' ;
2189 # History
2190 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2191 $r .= ')' ;
2194 $r .= $users ;
2195 $r .= "<br />\n" ;
2197 # Sub-entries
2198 $r .= '<div id="'.$rci.'" style="display:none">' ;
2199 foreach ( $block AS $rcObj ) {
2200 # Get rc_xxxx variables
2201 extract( $rcObj->mAttribs );
2203 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2204 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2205 if ( $rc_new ) $r .= $N ;
2206 else $r .= '&nbsp;' ;
2207 if ( $rc_minor ) $r .= $M ;
2208 else $r .= '&nbsp;' ;
2209 $r .= '</tt>' ;
2211 $o = '' ;
2212 if ( $rc_last_oldid != 0 ) {
2213 $o = 'oldid='.$rc_last_oldid ;
2215 if ( $rc_type == RC_LOG ) {
2216 $link = $rcObj->timestamp ;
2217 } else {
2218 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2220 $link = '<tt>'.$link.'</tt>' ;
2222 $r .= $link ;
2223 $r .= ' (' ;
2224 $r .= $rcObj->curlink ;
2225 $r .= '; ' ;
2226 $r .= $rcObj->lastlink ;
2227 $r .= ') . . '.$rcObj->userlink ;
2228 $r .= $rcObj->usertalklink ;
2229 if ( $rc_comment != '' ) {
2230 $rc_comment=$this->formatComment($rc_comment);
2231 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2233 $r .= "<br />\n" ;
2235 $r .= "</div>\n" ;
2237 $this->rcCacheIndex++ ;
2238 return $r ;
2241 # If enhanced RC is in use, this function takes the previously cached
2242 # RC lines, arranges them, and outputs the HTML
2243 function recentChangesBlock ()
2245 global $wgStylePath ;
2246 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2247 $blockOut = '';
2248 foreach ( $this->rc_cache AS $secureName => $block ) {
2249 if ( count ( $block ) < 2 ) {
2250 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2251 } else {
2252 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2256 return '<div>'.$blockOut.'</div>' ;
2259 # Called in a loop over all displayed RC entries
2260 # Either returns the line, or caches it for later use
2261 function recentChangesLine( &$rc, $watched = false )
2263 global $wgUser ;
2264 $usenew = $wgUser->getOption( 'usenewrc' );
2265 if ( $usenew )
2266 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2267 else
2268 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2269 return $line ;
2272 function recentChangesLineOld( &$rc, $watched = false )
2274 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2276 # Extract DB fields into local scope
2277 extract( $rc->mAttribs );
2278 $curIdEq = 'curid=' . $rc_cur_id;
2280 # Make date header if necessary
2281 $date = $wgLang->date( $rc_timestamp, true);
2282 $s = '';
2283 if ( $date != $this->lastdate ) {
2284 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2285 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2286 $this->lastdate = $date;
2287 $this->rclistOpen = true;
2290 # If this edit has not yet been patrolled, make it stick out
2291 $s .= ( ! $wgUseRCPatrol || $rc_patrolled ) ? '<li> ' : '<li class="not_patrolled"> ';
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 $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
2302 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2303 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2304 } else {
2305 # Diff link
2306 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2307 $diffLink = wfMsg( 'diff' );
2308 } else {
2309 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2310 ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2311 $rcidparam = "&rcid={$rc_id}";
2312 else
2313 $rcidparam = "";
2314 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2315 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2316 '', '', ' tabindex="'.$rc->counter.'"');
2318 $s .= '('.$diffLink.') (';
2320 # History link
2321 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2322 $s .= ') . . ';
2324 # M and N (minor and new)
2325 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2326 if ( $rc_type == RC_NEW ) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2328 # Article link
2329 # If it's a new article, there is no diff link, but if it hasn't been
2330 # patrolled yet, we need to give users a way to do so
2331 if ( $wgUseRCPatrol && $rc_type == RC_NEW && $rc_patrolled == 0 &&
2332 $wgUser->getID() != 0 && ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2333 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2334 else
2335 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2337 if ( $watched ) {
2338 $articleLink = '<strong>'.$articleLink.'</strong>';
2340 $s .= ' '.$articleLink;
2344 # Timestamp
2345 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2347 # User link (or contributions for unregistered users)
2348 if ( 0 == $rc_user ) {
2349 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2350 $rc_user_text, 'target=' . $rc_user_text );
2351 } else {
2352 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2354 $s .= $userLink;
2356 # User talk link
2357 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2358 global $wgDisableAnonTalk;
2359 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2360 $userTalkLink = '';
2361 } else {
2362 $utns=$wgLang->getNsText(NS_USER_TALK);
2363 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2365 # Block link
2366 $blockLink='';
2367 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2368 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2369 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2372 if($blockLink) {
2373 if($userTalkLink) $userTalkLink .= ' | ';
2374 $userTalkLink .= $blockLink;
2376 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2378 # Add comment
2379 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2380 $rc_comment=$this->formatComment($rc_comment);
2381 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2383 $s .= "</li>\n";
2385 return $s;
2388 function recentChangesLineNew( &$baseRC, $watched = false )
2390 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2392 # Create a specialised object
2393 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2395 # Extract fields from DB into the function scope (rc_xxxx variables)
2396 extract( $rc->mAttribs );
2397 $curIdEq = 'curid=' . $rc_cur_id;
2399 # If it's a new day, add the headline and flush the cache
2400 $date = $wgLang->date( $rc_timestamp, true);
2401 $ret = '';
2402 if ( $date != $this->lastdate ) {
2403 # Process current cache
2404 $ret = $this->recentChangesBlock () ;
2405 $this->rc_cache = array() ;
2406 $ret .= "<h4>{$date}</h4>\n";
2407 $this->lastdate = $date;
2410 # Make article link
2411 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2412 $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
2413 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2414 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2415 } else {
2416 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2419 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2420 $rc->watched = $watched ;
2421 $rc->link = $clink ;
2422 $rc->timestamp = $time;
2424 # Make "cur" and "diff" links
2425 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2426 $curLink = wfMsg( 'cur' );
2427 $diffLink = wfMsg( 'diff' );
2428 } else {
2429 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2430 $aprops = ' tabindex="'.$baseRC->counter.'"';
2431 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2432 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2435 # Make "last" link
2436 $titleObj = $rc->getTitle();
2437 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2438 $lastLink = wfMsg( 'last' );
2439 } else {
2440 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2441 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2444 # Make user link (or user contributions for unregistered users)
2445 if ( $rc_user == 0 ) {
2446 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2447 $rc_user_text, 'target=' . $rc_user_text );
2448 } else {
2449 $userLink = $this->makeLink( $wgLang->getNsText(
2450 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2453 $rc->userlink = $userLink;
2454 $rc->lastlink = $lastLink;
2455 $rc->curlink = $curLink;
2456 $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 = htmlspecialchars( $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 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2527 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2528 # Handle link renaming [[foo|text]] will show link as "text"
2529 if( "" != $match[3] ) {
2530 $text = $match[3];
2531 } else {
2532 $text = $match[1];
2534 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2535 # Media link; trail not supported.
2536 $linkRegexp = '/\[\[(.*?)\]\]/';
2537 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2538 } else {
2539 # Other kind of link
2540 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2541 $trail = $submatch[1];
2542 } else {
2543 $trail = "";
2545 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2546 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2548 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2550 return $comment;
2553 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2555 global $wgUser, $wgLang, $wgTitle;
2557 $datetime = $wgLang->timeanddate( $timestamp, true );
2558 $del = wfMsg( 'deleteimg' );
2559 $delall = wfMsg( 'deleteimgcompletely' );
2560 $cur = wfMsg( 'cur' );
2562 if ( $iscur ) {
2563 $url = Image::wfImageUrl( $img );
2564 $rlink = $cur;
2565 if ( $wgUser->isSysop() ) {
2566 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2567 '&action=delete' );
2568 $style = $this->getInternalLinkAttributes( $link, $delall );
2570 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2571 } else {
2572 $dlink = $del;
2574 } else {
2575 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2576 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2577 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2578 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2579 urlencode( $img ) );
2580 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2581 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2582 } else {
2583 # Having live active links for non-logged in users
2584 # means that bots and spiders crawling our site can
2585 # inadvertently change content. Baaaad idea.
2586 $rlink = wfMsg( 'revertimg' );
2587 $dlink = $del;
2590 if ( 0 == $user ) {
2591 $userlink = $usertext;
2592 } else {
2593 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2594 ':'.$usertext, $usertext );
2596 $nbytes = wfMsg( 'nbytes', $size );
2597 $style = $this->getInternalLinkAttributes( $url, $datetime );
2599 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2600 . " . . {$userlink} ({$nbytes})";
2602 if ( '' != $description && '*' != $description ) {
2603 $sk=$wgUser->getSkin();
2604 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2606 $s .= "</li>\n";
2607 return $s;
2610 function tocIndent($level) {
2611 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2614 function tocUnindent($level) {
2615 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2618 # parameter level defines if we are on an indentation level
2619 function tocLine( $anchor, $tocline, $level ) {
2620 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2621 if($level) {
2622 return $link."\n";
2623 } else {
2624 return '<div class="tocline">'.$link."</div>\n";
2629 function tocTable($toc) {
2630 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2631 # try min-width & co when somebody gets a chance
2632 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2633 return
2634 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2635 '<b>'.wfMsg('toc').'</b>' .
2636 $hideline .
2637 '</td></tr><tr id="tocinside"><td>'."\n".
2638 $toc."</td></tr></table>\n";
2641 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2642 function editSectionScript( $section, $head ) {
2643 global $wgTitle, $wgRequest;
2644 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2645 return $head;
2647 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2648 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2651 function editSectionLink( $section ) {
2652 global $wgRequest;
2653 global $wgTitle, $wgUser, $wgLang;
2655 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2656 # Section edit links would be out of sync on an old page.
2657 # But, if we're diffing to the current page, they'll be
2658 # correct.
2659 return '';
2662 $editurl = '&section='.$section;
2663 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2665 if( $wgLang->isRTL() ) {
2666 $farside = 'left';
2667 $nearside = 'right';
2668 } else {
2669 $farside = 'right';
2670 $nearside = 'left';
2672 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2676 // This function is called by EditPage.php and shows a bulletin board style
2677 // toolbar for common editing functions. It can be disabled in the user preferences.
2678 // The necsesary JavaScript code can be found in style/wikibits.js.
2679 function getEditToolbar() {
2680 global $wgStylePath, $wgLang, $wgMimeType;
2682 // toolarray an array of arrays which each include the filename of
2683 // the button image (without path), the opening tag, the closing tag,
2684 // and optionally a sample text that is inserted between the two when no
2685 // selection is highlighted.
2686 // The tip text is shown when the user moves the mouse over the button.
2688 // Already here are accesskeys (key), which are not used yet until someone
2689 // can figure out a way to make them work in IE. However, we should make
2690 // sure these keys are not defined on the edit page.
2691 $toolarray=array(
2692 array( 'image'=>'button_bold.png',
2693 'open'=>"\'\'\'",
2694 'close'=>"\'\'\'",
2695 'sample'=>wfMsg('bold_sample'),
2696 'tip'=>wfMsg('bold_tip'),
2697 'key'=>'B'
2699 array( "image"=>"button_italic.png",
2700 "open"=>"\'\'",
2701 "close"=>"\'\'",
2702 "sample"=>wfMsg("italic_sample"),
2703 "tip"=>wfMsg("italic_tip"),
2704 "key"=>"I"
2706 array( "image"=>"button_link.png",
2707 "open"=>"[[",
2708 "close"=>"]]",
2709 "sample"=>wfMsg("link_sample"),
2710 "tip"=>wfMsg("link_tip"),
2711 "key"=>"L"
2713 array( "image"=>"button_extlink.png",
2714 "open"=>"[",
2715 "close"=>"]",
2716 "sample"=>wfMsg("extlink_sample"),
2717 "tip"=>wfMsg("extlink_tip"),
2718 "key"=>"X"
2720 array( "image"=>"button_headline.png",
2721 "open"=>"\\n== ",
2722 "close"=>" ==\\n",
2723 "sample"=>wfMsg("headline_sample"),
2724 "tip"=>wfMsg("headline_tip"),
2725 "key"=>"H"
2727 array( "image"=>"button_image.png",
2728 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2729 "close"=>"]]",
2730 "sample"=>wfMsg("image_sample"),
2731 "tip"=>wfMsg("image_tip"),
2732 "key"=>"D"
2734 array( "image"=>"button_media.png",
2735 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2736 "close"=>"]]",
2737 "sample"=>wfMsg("media_sample"),
2738 "tip"=>wfMsg("media_tip"),
2739 "key"=>"M"
2741 array( "image"=>"button_math.png",
2742 "open"=>"\\<math\\>",
2743 "close"=>"\\</math\\>",
2744 "sample"=>wfMsg("math_sample"),
2745 "tip"=>wfMsg("math_tip"),
2746 "key"=>"C"
2748 array( "image"=>"button_nowiki.png",
2749 "open"=>"\\<nowiki\\>",
2750 "close"=>"\\</nowiki\\>",
2751 "sample"=>wfMsg("nowiki_sample"),
2752 "tip"=>wfMsg("nowiki_tip"),
2753 "key"=>"N"
2755 array( "image"=>"button_sig.png",
2756 "open"=>"--~~~~",
2757 "close"=>"",
2758 "sample"=>"",
2759 "tip"=>wfMsg("sig_tip"),
2760 "key"=>"Y"
2762 array( "image"=>"button_hr.png",
2763 "open"=>"\\n----\\n",
2764 "close"=>"",
2765 "sample"=>"",
2766 "tip"=>wfMsg("hr_tip"),
2767 "key"=>"R"
2770 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2772 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2773 foreach($toolarray as $tool) {
2775 $image=$wgStylePath.'/images/'.$tool['image'];
2776 $open=$tool['open'];
2777 $close=$tool['close'];
2778 $sample = addslashes( $tool['sample'] );
2780 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2781 // Older browsers show a "speedtip" type message only for ALT.
2782 // Ideally these should be different, realistically they
2783 // probably don't need to be.
2784 $tip = addslashes( $tool['tip'] );
2786 #$key = $tool["key"];
2788 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2791 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2792 $toolbar.="document.writeln(\"</div>\");\n";
2794 $toolbar.="/*]]>*/\n</script>";
2795 return $toolbar;
2798 /* public */ function suppressUrlExpansion() {
2799 return false;