With &debugmsg=1, PHP output a warning because the link trail no longer
[mediawiki.git] / includes / Skin.php
blob8e087ceb922e1e4e67f259003b3c4401baba0d85
1 <?php
2 if( defined( "MEDIAWIKI" ) ) {
4 # See skin.doc
6 require_once( 'Feed.php' ); // should not be called if the actual page isn't feed enabled
7 require_once( 'Image.php' );
9 # These are the INTERNAL names, which get mapped
10 # directly to class names. For display purposes, the
11 # Language class has internationalized names
13 /* private */ $wgValidSkinNames = array(
14 'standard' => 'Standard',
15 'nostalgia' => 'Nostalgia',
16 'cologneblue' => 'CologneBlue'
18 if( $wgUsePHPTal ) {
19 #$wgValidSkinNames[] = 'PHPTal';
20 #$wgValidSkinNames['davinci'] = 'DaVinci';
21 #$wgValidSkinNames['mono'] = 'Mono';
22 $wgValidSkinNames['monobook'] = 'MonoBook';
23 $wgValidSkinNames['myskin'] = 'MySkin';
24 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
27 require_once( 'RecentChange.php' );
29 class RCCacheEntry extends RecentChange
31 var $secureName, $link;
32 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
33 var $userlink, $timestamp, $watched;
35 function newFromParent( $rc )
37 $rc2 = new RCCacheEntry;
38 $rc2->mAttribs = $rc->mAttribs;
39 $rc2->mExtra = $rc->mExtra;
40 return $rc2;
42 } ;
44 class Skin {
46 /* private */ var $lastdate, $lastline;
47 var $linktrail ; # linktrail regexp
48 var $rc_cache ; # Cache for Enhanced Recent Changes
49 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
50 var $rcMoveIndex;
51 var $postParseLinkColour = true;
53 function Skin()
55 $this->linktrail = wfMsg('linktrail');
58 function getSkinNames()
60 global $wgValidSkinNames;
61 return $wgValidSkinNames;
64 function getStylesheet()
66 return 'wikistandard.css';
68 function getSkinName() {
69 return "standard";
72 # Get/set accessor for delayed link colouring
73 function postParseLinkColour( $setting = NULL ) {
74 return wfSetVar( $this->postParseLinkColour, $setting );
77 function qbSetting()
79 global $wgOut, $wgUser;
81 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
82 $q = $wgUser->getOption( 'quickbar' );
83 if ( '' == $q ) { $q = 0; }
84 return $q;
87 function initPage( &$out )
89 $fname = 'Skin::initPage';
90 wfProfileIn( $fname );
92 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
94 $this->addMetadataLinks($out);
96 wfProfileOut( $fname );
99 function addMetadataLinks( &$out ) {
100 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
101 global $wgRightsPage, $wgRightsUrl;
103 if( $out->isArticleRelated() ) {
104 # note: buggy CC software only reads first "meta" link
105 if( $wgEnableCreativeCommonsRdf ) {
106 $out->addMetadataLink( array(
107 'title' => 'Creative Commons',
108 'type' => 'application/rdf+xml',
109 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
111 if( $wgEnableDublinCoreRdf ) {
112 $out->addMetadataLink( array(
113 'title' => 'Dublin Core',
114 'type' => 'application/rdf+xml',
115 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
118 $copyright = '';
119 if( $wgRightsPage ) {
120 $copy = Title::newFromText( $wgRightsPage );
121 if( $copy ) {
122 $copyright = $copy->getLocalURL();
125 if( !$copyright && $wgRightsUrl ) {
126 $copyright = $wgRightsUrl;
128 if( $copyright ) {
129 $out->addLink( array(
130 'rel' => 'copyright',
131 'href' => $copyright ) );
135 function outputPage( &$out ) {
136 global $wgDebugComments;
138 wfProfileIn( 'Skin::outputPage' );
139 $this->initPage( $out );
140 $out->out( $out->headElement() );
142 $out->out( "\n<body" );
143 $ops = $this->getBodyOptions();
144 foreach ( $ops as $name => $val ) {
145 $out->out( " $name='$val'" );
147 $out->out( ">\n" );
148 if ( $wgDebugComments ) {
149 $out->out( "<!-- Wiki debugging output:\n" .
150 $out->mDebugtext . "-->\n" );
152 $out->out( $this->beforeContent() );
154 $out->out( $out->mBodytext . "\n" );
156 $out->out( $this->afterContent() );
158 wfProfileClose();
159 $out->out( $out->reportTime() );
161 $out->out( "\n</body></html>" );
164 function getHeadScripts() {
165 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
166 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
167 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
168 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
169 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
170 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
172 return $r;
175 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
176 function getUserStylesheet() {
177 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
178 $sheet = $this->getStylesheet();
179 $action = $wgRequest->getText('action');
180 $s = "@import \"$wgStylePath/$sheet\";\n";
181 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
182 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
183 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
184 $s .= $wgRequest->getText('wpTextbox1');
185 } else {
186 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
187 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
190 $s .= $this->doGetUserStyles();
191 return $s."\n";
193 # placeholder, returns generated js in monobook
194 function getUserJs() {
195 return;
198 function getUserStyles()
200 global $wgOut, $wgStylePath, $wgLang;
201 $s = "<style type='text/css'>\n";
202 $s .= "/*/*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
203 $s .= $this->getUserStylesheet();
204 $s .= "/* */\n";
205 $s .= "</style>\n";
206 return $s;
209 function doGetUserStyles()
211 global $wgUser, $wgLang;
213 $csspage = $wgLang->getNsText( NS_MEDIAWIKI ) . ":" . $this->getSkinName() . ".css";
214 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
216 if ( 1 == $wgUser->getOption( 'underline' ) ) {
217 # Don't override browser settings
218 } else {
219 # CHECK MERGE @@@
220 # Force no underline
221 $s .= "a { text-decoration: none; }\n";
223 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
224 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
226 if ( 1 == $wgUser->getOption( 'justify' ) ) {
227 $s .= "#article { text-align: justify; }\n";
229 return $s;
232 function getBodyOptions()
234 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
236 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
238 if ( 0 != $wgTitle->getNamespace() ) {
239 $a = array( 'bgcolor' => '#ffffec' );
241 else $a = array( 'bgcolor' => '#FFFFFF' );
242 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
243 (!$wgTitle->isProtected() || $wgUser->isSysop()) ) {
244 $t = wfMsg( 'editthispage' );
245 $oid = $red = '';
246 if ( !empty($redirect) ) {
247 $red = "&redirect={$redirect}";
249 if ( !empty($oldid) && ! isset( $diff ) ) {
250 $oid = "&oldid={$oldid}";
252 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
253 $s = 'document.location = "' .$s .'";';
254 $a += array ('ondblclick' => $s);
257 $a['onload'] = $wgOut->getOnloadHandler();
258 return $a;
261 function getExternalLinkAttributes( $link, $text, $class='' )
263 global $wgUser, $wgOut, $wgLang;
265 $link = urldecode( $link );
266 $link = $wgLang->checkTitleEncoding( $link );
267 $link = str_replace( '_', ' ', $link );
268 $link = wfEscapeHTML( $link );
270 $r = ($class != '') ? " class='$class'" : " class='external'";
272 if ( 1 == $wgUser->getOption( 'hover' ) ) {
273 $r .= " title=\"{$link}\"";
275 return $r;
278 function getInternalLinkAttributes( $link, $text, $broken = false )
280 global $wgUser, $wgOut;
282 $link = urldecode( $link );
283 $link = str_replace( '_', ' ', $link );
284 $link = wfEscapeHTML( $link );
286 if ( $broken == 'stub' ) {
287 $r = ' class="stub"';
288 } else if ( $broken == 'yes' ) {
289 $r = ' class="new"';
290 } else {
291 $r = '';
294 if ( 1 == $wgUser->getOption( 'hover' ) ) {
295 $r .= " title=\"{$link}\"";
297 return $r;
300 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
302 global $wgUser, $wgOut;
304 if ( $broken == 'stub' ) {
305 $r = ' class="stub"';
306 } else if ( $broken == 'yes' ) {
307 $r = ' class="new"';
308 } else {
309 $r = '';
312 if ( 1 == $wgUser->getOption( 'hover' ) ) {
313 $r .= ' title ="' . $nt->getEscapedText() . '"';
315 return $r;
318 function getLogo()
320 global $wgLogo;
321 return $wgLogo;
324 # This will be called immediately after the <body> tag. Split into
325 # two functions to make it easier to subclass.
327 function beforeContent()
329 global $wgUser, $wgOut;
331 return $this->doBeforeContent();
334 function doBeforeContent()
336 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
337 $fname = 'Skin::doBeforeContent';
338 wfProfileIn( $fname );
340 $s = '';
341 $qb = $this->qbSetting();
343 if( $langlinks = $this->otherLanguages() ) {
344 $rows = 2;
345 $borderhack = '';
346 } else {
347 $rows = 1;
348 $langlinks = false;
349 $borderhack = 'class="top"';
352 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
353 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
355 $shove = ($qb != 0);
356 $left = ($qb == 1 || $qb == 3);
357 if($wgLang->isRTL()) $left = !$left;
359 if ( !$shove ) {
360 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
361 $this->logoText() . '</td>';
362 } elseif( $left ) {
363 $s .= $this->getQuickbarCompensator( $rows );
365 $l = $wgLang->isRTL() ? 'right' : 'left';
366 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
368 $s .= $this->topLinks() ;
369 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
371 $r = $wgLang->isRTL() ? "left" : "right";
372 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
373 $s .= $this->nameAndLogin();
374 $s .= "\n<br />" . $this->searchForm() . "</td>";
376 if ( $langlinks ) {
377 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
380 if ( $shove && !$left ) { # Right
381 $s .= $this->getQuickbarCompensator( $rows );
383 $s .= "</tr>\n</table>\n</div>\n";
384 $s .= "\n<div id='article'>\n";
386 if( $wgSiteNotice ) {
387 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
389 $s .= $this->pageTitle();
390 $s .= $this->pageSubtitle() ;
391 $s .= $this->getCategories();
392 wfProfileOut( $fname );
393 return $s;
396 function getCategoryLinks () {
397 global $wgOut, $wgTitle, $wgUser, $wgParser;
398 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
400 if( !$wgUseCategoryMagic ) return '' ;
401 if( count( $wgOut->mCategoryLinks ) == 0 ) return '';
403 # Taken out so that they will be displayed in previews -- TS
404 #if( !$wgOut->isArticle() ) return '';
406 $t = implode ( ' | ' , $wgOut->mCategoryLinks ) ;
407 $s = $this->makeKnownLink( 'Special:Categories',
408 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
409 . ': ' . $t;
411 if($wgUseCategoryBrowser) {
412 $s .= '<br/><hr/>';
413 $catstack = array();
414 $s.= $wgTitle->getAllParentCategories($catstack);
417 return $s;
420 function getCategories() {
421 $catlinks=$this->getCategoryLinks();
422 if(!empty($catlinks)) {
423 return "<p class='catlinks'>{$catlinks}</p>";
427 function getQuickbarCompensator( $rows = 1 )
429 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
432 # This gets called immediately before the </body> tag.
434 function afterContent()
436 global $wgUser, $wgOut, $wgServer;
437 global $wgTitle, $wgLang;
439 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
440 return $printfooter . $this->doAfterContent();
443 function printSource() {
444 global $wgTitle;
445 $url = htmlspecialchars( $wgTitle->getFullURL() );
446 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
449 function printFooter() {
450 return "<p>" . $this->printSource() .
451 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
454 function doAfterContent()
456 global $wgUser, $wgOut, $wgLang;
457 $fname = 'Skin::doAfterContent';
458 wfProfileIn( $fname );
459 wfProfileIn( $fname.'-1' );
461 $s = "\n</div><br style=\"clear:both\" />\n";
462 $s .= "\n<div id='footer'>";
463 $s .= '<table border="0" cellspacing="0"><tr>';
465 wfProfileOut( $fname.'-1' );
466 wfProfileIn( $fname.'-2' );
468 $qb = $this->qbSetting();
469 $shove = ($qb != 0);
470 $left = ($qb == 1 || $qb == 3);
471 if($wgLang->isRTL()) $left = !$left;
473 if ( $shove && $left ) { # Left
474 $s .= $this->getQuickbarCompensator();
476 wfProfileOut( $fname.'-2' );
477 wfProfileIn( $fname.'-3' );
478 $l = $wgLang->isRTL() ? 'right' : 'left';
479 $s .= "<td class='bottom' align='$l' valign='top'>";
481 $s .= $this->bottomLinks();
482 $s .= "\n<br />" . $this->mainPageLink()
483 . ' | ' . $this->aboutLink()
484 . ' | ' . $this->specialLink( 'recentchanges' )
485 . ' | ' . $this->searchForm()
486 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
488 $s .= "</td>";
489 if ( $shove && !$left ) { # Right
490 $s .= $this->getQuickbarCompensator();
492 $s .= "</tr></table>\n</div>\n</div>\n";
494 wfProfileOut( $fname.'-3' );
495 wfProfileIn( $fname.'-4' );
496 if ( 0 != $qb ) { $s .= $this->quickBar(); }
497 wfProfileOut( $fname.'-4' );
498 wfProfileOut( $fname );
499 return $s;
502 function pageTitleLinks()
504 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
506 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
507 $action = $wgRequest->getText( 'action' );
509 $s = $this->printableLink();
510 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
512 if ( $wgOut->isArticleRelated() ) {
513 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
514 $name = $wgTitle->getDBkey();
515 $link = wfEscapeHTML( Image::wfImageUrl( $name ) );
516 $style = $this->getInternalLinkAttributes( $link, $name );
517 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
519 # This will show the "Approve" link if $wgUseApproval=true;
520 if ( isset ( $wgUseApproval ) && $wgUseApproval )
522 $t = $wgTitle->getDBkey();
523 $name = 'Approve this article' ;
524 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
525 #wfEscapeHTML( wfImageUrl( $name ) );
526 $style = $this->getExternalLinkAttributes( $link, $name );
527 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
530 if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) {
531 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
532 wfMsg( 'currentrev' ) );
535 if ( $wgUser->getNewtalk() ) {
536 # do not show "You have new messages" text when we are viewing our
537 # own talk page
539 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
540 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
541 $n =$wgUser->getName();
542 $tl = $this->makeKnownLink( $wgLang->getNsText(
543 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
544 wfMsg('newmessageslink') );
545 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
549 $undelete = $this->getUndeleteLink();
550 if( !empty( $undelete ) ) {
551 $s .= ' | '.$undelete;
553 return $s;
556 function getUndeleteLink() {
557 global $wgUser, $wgTitle, $wgLang, $action;
558 if( $wgUser->isSysop() &&
559 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
560 ($n = $wgTitle->isDeleted() ) ) {
561 return wfMsg( 'thisisdeleted',
562 $this->makeKnownLink(
563 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
564 wfMsg( 'restorelink', $n ) ) );
566 return '';
569 function printableLink()
571 global $wgOut, $wgFeedClasses, $wgRequest;
573 $baseurl = $_SERVER['REQUEST_URI'];
574 if( strpos( '?', $baseurl ) == false ) {
575 $baseurl .= '?';
576 } else {
577 $baseurl .= '&';
579 $baseurl = htmlspecialchars( $baseurl );
580 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
582 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
583 if( $wgOut->isSyndicated() ) {
584 foreach( $wgFeedClasses as $format => $class ) {
585 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
586 $s .= " | <a href=\"$feedurl\">{$format}</a>";
589 return $s;
592 function pageTitle()
594 global $wgOut, $wgTitle, $wgUser;
596 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
597 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
598 return $s;
601 function pageSubtitle()
603 global $wgOut;
605 $sub = $wgOut->getSubtitle();
606 if ( '' == $sub ) {
607 global $wgExtraSubtitle;
608 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
610 $subpages = $this->subPageSubtitle();
611 $sub .= !empty($subpages)?"</p><p class='subpages'>$subpages":'';
612 $s = "<p class='subtitle'>{$sub}</p>\n";
613 return $s;
616 function subPageSubtitle()
618 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
619 $subpages = '';
620 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
621 $ptext=$wgTitle->getPrefixedText();
622 if(preg_match('/\//',$ptext)) {
623 $links = explode('/',$ptext);
624 $c = 0;
625 $growinglink = '';
626 foreach($links as $link) {
627 $c++;
628 if ($c<count($links)) {
629 $growinglink .= $link;
630 $getlink = $this->makeLink( $growinglink, $link );
631 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
632 if ($c>1) {
633 $subpages .= ' | ';
634 } else {
635 $subpages .= '&lt; ';
637 $subpages .= $getlink;
638 $growinglink .= '/';
643 return $subpages;
646 function nameAndLogin()
648 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
650 $li = $wgLang->specialPage( 'Userlogin' );
651 $lo = $wgLang->specialPage( 'Userlogout' );
653 $s = '';
654 if ( 0 == $wgUser->getID() ) {
655 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
656 $n = $wgIP;
658 $tl = $this->makeKnownLink( $wgLang->getNsText(
659 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
660 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
662 $s .= $n . ' ('.$tl.')';
663 } else {
664 $s .= wfMsg('notloggedin');
667 $rt = $wgTitle->getPrefixedURL();
668 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
669 $q = '';
670 } else { $q = "returnto={$rt}"; }
672 $s .= "\n<br />" . $this->makeKnownLink( $li,
673 wfMsg( 'login' ), $q );
674 } else {
675 $n = $wgUser->getName();
676 $rt = $wgTitle->getPrefixedURL();
677 $tl = $this->makeKnownLink( $wgLang->getNsText(
678 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
679 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
681 $tl = " ({$tl})";
683 $s .= $this->makeKnownLink( $wgLang->getNsText(
684 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
685 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
686 "returnto={$rt}" ) . ' | ' .
687 $this->specialLink( 'preferences' );
689 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
690 wfMsg( 'help' ) );
692 return $s;
695 function getSearchLink() {
696 $searchPage =& Title::makeTitle( NS_SPECIAL, 'Search' );
697 return $searchPage->getLocalURL();
700 function escapeSearchLink() {
701 return htmlspecialchars( $this->getSearchLink() );
704 function searchForm()
706 global $wgRequest;
707 $search = $wgRequest->getText( 'search' );
709 $s = '<form name="search" class="inline" method="post" action="'
710 . $this->escapeSearchLink() . "\">\n"
711 . '<input type="text" name="search" size="19" value="'
712 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
713 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" />&nbsp;'
714 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
716 return $s;
719 function topLinks()
721 global $wgOut;
722 $sep = " |\n";
724 $s = $this->mainPageLink() . $sep
725 . $this->specialLink( 'recentchanges' );
727 if ( $wgOut->isArticleRelated() ) {
728 $s .= $sep . $this->editThisPage()
729 . $sep . $this->historyLink();
731 # Many people don't like this dropdown box
732 #$s .= $sep . $this->specialPagesList();
734 return $s;
737 function bottomLinks()
739 global $wgOut, $wgUser, $wgTitle;
740 $sep = " |\n";
742 $s = '';
743 if ( $wgOut->isArticleRelated() ) {
744 $s .= '<strong>' . $this->editThisPage() . '</strong>';
745 if ( 0 != $wgUser->getID() ) {
746 $s .= $sep . $this->watchThisPage();
748 $s .= $sep . $this->talkLink()
749 . $sep . $this->historyLink()
750 . $sep . $this->whatLinksHere()
751 . $sep . $this->watchPageLinksLink();
753 if ( $wgTitle->getNamespace() == Namespace::getUser()
754 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
757 $id=User::idFromName($wgTitle->getText());
758 $ip=User::isIP($wgTitle->getText());
760 if($id || $ip) { # both anons and non-anons have contri list
761 $s .= $sep . $this->userContribsLink();
763 if ( 0 != $wgUser->getID() ) { # show only to signed in users
764 if($id) { # can only email non-anons
765 $s .= $sep . $this->emailUserLink();
769 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
770 $s .= "\n<br />" . $this->deleteThisPage() .
771 $sep . $this->protectThisPage() .
772 $sep . $this->moveThisPage();
774 $s .= "<br />\n" . $this->otherLanguages();
776 return $s;
779 function pageStats()
781 global $wgOut, $wgLang, $wgArticle, $wgRequest;
782 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
784 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
785 if ( ! $wgOut->isArticle() ) { return ''; }
786 if ( isset( $oldid ) || isset( $diff ) ) { return ''; }
787 if ( 0 == $wgArticle->getID() ) { return ''; }
789 $s = '';
790 if ( !$wgDisableCounters ) {
791 $count = $wgLang->formatNum( $wgArticle->getCount() );
792 if ( $count ) {
793 $s = wfMsg( 'viewcount', $count );
797 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
798 require_once("Credits.php");
799 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
800 } else {
801 $s .= $this->lastModified();
804 return $s . ' ' . $this->getCopyright();
807 function getCopyright() {
808 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
811 $oldid = $wgRequest->getVal( 'oldid' );
812 $diff = $wgRequest->getVal( 'diff' );
814 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
815 $msg = 'history_copyright';
816 } else {
817 $msg = 'copyright';
820 $out = '';
821 if( $wgRightsPage ) {
822 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
823 } elseif( $wgRightsUrl ) {
824 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
825 } else {
826 # Give up now
827 return $out;
829 $out .= wfMsg( $msg, $link );
830 return $out;
833 function getCopyrightIcon() {
834 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
835 $out = '';
836 if( $wgRightsIcon ) {
837 $icon = htmlspecialchars( $wgRightsIcon );
838 if( $wgRightsUrl ) {
839 $url = htmlspecialchars( $wgRightsUrl );
840 $out .= '<a href="'.$url.'">';
842 $text = htmlspecialchars( $wgRightsText );
843 $out .= "<img src=\"$icon\" alt='$text' />";
844 if( $wgRightsUrl ) {
845 $out .= '</a>';
848 return $out;
851 function getPoweredBy() {
852 global $wgStylePath;
853 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
854 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
855 return $img;
858 function lastModified()
860 global $wgLang, $wgArticle;
862 $timestamp = $wgArticle->getTimestamp();
863 if ( $timestamp ) {
864 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
865 $s = ' ' . wfMsg( 'lastmodified', $d );
866 } else {
867 $s = '';
869 return $s;
872 function logoText( $align = '' )
874 if ( '' != $align ) { $a = ' align="'.$align.'"'; }
875 else { $a = ''; }
877 $mp = wfMsg( 'mainpage' );
878 $titleObj = Title::newFromText( $mp );
879 $s = '<a href="' . $titleObj->escapeLocalURL()
880 . '"><img'.$a.' src="'
881 . $this->getLogo() . '" alt="' . "[{$mp}]\" /></a>";
882 return $s;
885 function quickBar()
887 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
888 global $wgDisableUploads, $wgRemoteUploads;
890 $fname = 'Skin::quickBar';
891 wfProfileIn( $fname );
893 $action = $wgRequest->getText( 'action' );
894 $wpPreview = $wgRequest->getBool( 'wpPreview' );
895 $tns=$wgTitle->getNamespace();
897 $s = "\n<div id='quickbar'>";
898 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
900 $sep = "\n<br />";
901 $s .= $this->mainPageLink()
902 . $sep . $this->specialLink( 'recentchanges' )
903 . $sep . $this->specialLink( 'randompage' );
904 if ($wgUser->getID()) {
905 $s.= $sep . $this->specialLink( 'watchlist' ) ;
906 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
907 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
910 // only show watchlist link if logged in
911 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
912 $s .= "\n<br /><hr class='sep' />";
913 $articleExists = $wgTitle->getArticleId();
914 if ( $wgOut->isArticle() || $action =='edit' || $action =='history' || $wpPreview) {
915 if($wgOut->isArticle()) {
916 $s .= '<strong>' . $this->editThisPage() . '</strong>';
917 } else { # backlink to the article in edit or history mode
918 if($articleExists){ # no backlink if no article
919 switch($tns) {
920 case 0:
921 $text = wfMsg('articlepage');
922 break;
923 case 1:
924 $text = wfMsg('viewtalkpage');
925 break;
926 case 2:
927 $text = wfMsg('userpage');
928 break;
929 case 3:
930 $text = wfMsg('viewtalkpage');
931 break;
932 case 4:
933 $text = wfMsg('wikipediapage');
934 break;
935 case 5:
936 $text = wfMsg('viewtalkpage');
937 break;
938 case 6:
939 $text = wfMsg('imagepage');
940 break;
941 case 7:
942 $text = wfMsg('viewtalkpage');
943 break;
944 default:
945 $text= wfMsg('articlepage');
948 $link = $wgTitle->getText();
949 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
950 $link = $nstext . ':' . $link ;
953 $s .= $this->makeLink( $link, $text );
954 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
955 # we just throw in a "New page" text to tell the user that he's in edit mode,
956 # and to avoid messing with the separator that is prepended to the next item
957 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
963 if( $tns%2 && $action!='edit' && !$wpPreview) {
964 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit&section=new');
968 watching could cause problems in edit mode:
969 if user edits article, then loads "watch this article" in background and then saves
970 article with "Watch this article" checkbox disabled, the article is transparently
971 unwatched. Therefore we do not show the "Watch this page" link in edit mode
973 if ( 0 != $wgUser->getID() && $articleExists) {
974 if($action!='edit' && $action != 'submit' )
976 $s .= $sep . $this->watchThisPage();
978 if ( $wgTitle->userCanEdit() )
979 $s .= $sep . $this->moveThisPage();
981 if ( $wgUser->isSysop() and $articleExists ) {
982 $s .= $sep . $this->deleteThisPage() .
983 $sep . $this->protectThisPage();
985 $s .= $sep . $this->talkLink();
986 if ($articleExists && $action !='history') {
987 $s .= $sep . $this->historyLink();
989 $s.=$sep . $this->whatLinksHere();
991 if($wgOut->isArticleRelated()) {
992 $s .= $sep . $this->watchPageLinksLink();
995 if ( Namespace::getUser() == $wgTitle->getNamespace()
996 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
999 $id=User::idFromName($wgTitle->getText());
1000 $ip=User::isIP($wgTitle->getText());
1002 if($id||$ip) {
1003 $s .= $sep . $this->userContribsLink();
1005 if ( 0 != $wgUser->getID() ) {
1006 if($id) { # can only email real users
1007 $s .= $sep . $this->emailUserLink();
1011 $s .= "\n<br /><hr class='sep' />";
1014 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
1015 $s .= $this->specialLink( 'upload' ) . $sep;
1017 $s .= $this->specialLink( 'specialpages' )
1018 . $sep . $this->bugReportsLink();
1020 global $wgSiteSupportPage;
1021 if( $wgSiteSupportPage ) {
1022 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1023 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1026 $s .= "\n<br /></div>\n";
1027 wfProfileOut( $fname );
1028 return $s;
1031 function specialPagesList()
1033 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1034 require_once('SpecialPage.php');
1035 $a = array();
1036 $pages = SpecialPage::getPages();
1038 foreach ( $pages[''] as $name => $page ) {
1039 $a[$name] = $page->getDescription();
1041 if ( $wgUser->isSysop() )
1043 foreach ( $pages['sysop'] as $name => $page ) {
1044 $a[$name] = $page->getDescription();
1047 if ( $wgUser->isDeveloper() )
1049 foreach ( $pages['developer'] as $name => $page ) {
1050 $a[$name] = $page->getDescription() ;
1053 $go = wfMsg( 'go' );
1054 $sp = wfMsg( 'specialpages' );
1055 $spp = $wgLang->specialPage( 'Specialpages' );
1057 $s = '<form id="specialpages" method="get" class="inline" ' .
1058 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1059 $s .= "<select name=\"wpDropdown\">\n";
1060 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1062 foreach ( $a as $name => $desc ) {
1063 $p = $wgLang->specialPage( $name );
1064 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1066 $s .= "</select>\n";
1067 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1068 $s .= "</form>\n";
1069 return $s;
1072 function mainPageLink()
1074 $mp = wfMsg( 'mainpage' );
1075 $s = $this->makeKnownLink( $mp, $mp );
1076 return $s;
1079 function copyrightLink()
1081 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1082 wfMsg( 'copyrightpagename' ) );
1083 return $s;
1086 function aboutLink()
1088 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1089 wfMsg( 'aboutwikipedia' ) );
1090 return $s;
1094 function disclaimerLink()
1096 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1097 wfMsg( 'disclaimers' ) );
1098 return $s;
1101 function editThisPage()
1103 global $wgOut, $wgTitle, $wgRequest;
1105 $oldid = $wgRequest->getVal( 'oldid' );
1106 $diff = $wgRequest->getVal( 'diff' );
1107 $redirect = $wgRequest->getVal( 'redirect' );
1109 if ( ! $wgOut->isArticleRelated() ) {
1110 $s = wfMsg( 'protectedpage' );
1111 } else {
1112 $n = $wgTitle->getPrefixedText();
1113 if ( $wgTitle->userCanEdit() ) {
1114 $t = wfMsg( 'editthispage' );
1115 } else {
1116 #$t = wfMsg( "protectedpage" );
1117 $t = wfMsg( 'viewsource' );
1119 $oid = $red = '';
1121 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1122 if ( $oldid && ! isset( $diff ) ) {
1123 $oid = "&oldid={$oldid}";
1125 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1127 return $s;
1130 function deleteThisPage()
1132 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1134 $diff = $wgRequest->getVal( 'diff' );
1135 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1136 $n = $wgTitle->getPrefixedText();
1137 $t = wfMsg( 'deletethispage' );
1139 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1140 } else {
1141 $s = '';
1143 return $s;
1146 function protectThisPage()
1148 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1150 $diff = $wgRequest->getVal( 'diff' );
1151 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1152 $n = $wgTitle->getPrefixedText();
1154 if ( $wgTitle->isProtected() ) {
1155 $t = wfMsg( 'unprotectthispage' );
1156 $q = 'action=unprotect';
1157 } else {
1158 $t = wfMsg( 'protectthispage' );
1159 $q = 'action=protect';
1161 $s = $this->makeKnownLink( $n, $t, $q );
1162 } else {
1163 $s = '';
1165 return $s;
1168 function watchThisPage()
1170 global $wgUser, $wgOut, $wgTitle;
1172 if ( $wgOut->isArticleRelated() ) {
1173 $n = $wgTitle->getPrefixedText();
1175 if ( $wgTitle->userIsWatching() ) {
1176 $t = wfMsg( 'unwatchthispage' );
1177 $q = 'action=unwatch';
1178 } else {
1179 $t = wfMsg( 'watchthispage' );
1180 $q = 'action=watch';
1182 $s = $this->makeKnownLink( $n, $t, $q );
1183 } else {
1184 $s = wfMsg( 'notanarticle' );
1186 return $s;
1189 function moveThisPage()
1191 global $wgTitle, $wgLang;
1193 if ( $wgTitle->userCanEdit() ) {
1194 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1195 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1196 } // no message if page is protected - would be redundant
1197 return $s;
1200 function historyLink()
1202 global $wgTitle;
1204 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1205 wfMsg( 'history' ), 'action=history' );
1206 return $s;
1209 function whatLinksHere()
1211 global $wgTitle, $wgLang;
1213 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1214 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1215 return $s;
1218 function userContribsLink()
1220 global $wgTitle, $wgLang;
1222 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1223 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1224 return $s;
1227 function emailUserLink()
1229 global $wgTitle, $wgLang;
1231 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1232 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1233 return $s;
1236 function watchPageLinksLink()
1238 global $wgOut, $wgTitle, $wgLang;
1240 if ( ! $wgOut->isArticleRelated() ) {
1241 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1242 } else {
1243 $s = $this->makeKnownLink( $wgLang->specialPage(
1244 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1245 'target=' . $wgTitle->getPrefixedURL() );
1247 return $s;
1250 function otherLanguages()
1252 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1254 $a = $wgOut->getLanguageLinks();
1255 if ( 0 == count( $a ) ) {
1256 if ( !$wgUseNewInterlanguage ) return '';
1257 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1258 if ( $ns != 0 AND $ns != 1 ) return '' ;
1259 $pn = 'Intl' ;
1260 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1261 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1262 wfMsg( 'intl' ) , $x );
1265 if ( !$wgUseNewInterlanguage ) {
1266 $s = wfMsg( 'otherlanguages' ) . ': ';
1267 } else {
1268 global $wgLanguageCode ;
1269 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1270 $x .= '&xl='.$wgLanguageCode ;
1271 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1272 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1275 $s = wfMsg( 'otherlanguages' ) . ': ';
1276 $first = true;
1277 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1278 foreach( $a as $l ) {
1279 if ( ! $first ) { $s .= ' | '; }
1280 $first = false;
1282 $nt = Title::newFromText( $l );
1283 $url = $nt->getFullURL();
1284 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1286 if ( '' == $text ) { $text = $l; }
1287 $style = $this->getExternalLinkAttributes( $l, $text );
1288 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1290 if($wgLang->isRTL()) $s .= '</span>';
1291 return $s;
1294 function bugReportsLink()
1296 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1297 wfMsg( 'bugreports' ) );
1298 return $s;
1301 function dateLink()
1303 global $wgLinkCache;
1304 $t1 = Title::newFromText( gmdate( 'F j' ) );
1305 $t2 = Title::newFromText( gmdate( 'Y' ) );
1307 $wgLinkCache->suspend();
1308 $id = $t1->getArticleID();
1309 $wgLinkCache->resume();
1311 if ( 0 == $id ) {
1312 $s = $this->makeBrokenLink( $t1->getText() );
1313 } else {
1314 $s = $this->makeKnownLink( $t1->getText() );
1316 $s .= ', ';
1318 $wgLinkCache->suspend();
1319 $id = $t2->getArticleID();
1320 $wgLinkCache->resume();
1322 if ( 0 == $id ) {
1323 $s .= $this->makeBrokenLink( $t2->getText() );
1324 } else {
1325 $s .= $this->makeKnownLink( $t2->getText() );
1327 return $s;
1330 function talkLink()
1332 global $wgLang, $wgTitle, $wgLinkCache;
1334 $tns = $wgTitle->getNamespace();
1335 if ( -1 == $tns ) { return ''; }
1337 $pn = $wgTitle->getText();
1338 $tp = wfMsg( 'talkpage' );
1339 if ( Namespace::isTalk( $tns ) ) {
1340 $lns = Namespace::getSubject( $tns );
1341 switch($tns) {
1342 case 1:
1343 $text = wfMsg('articlepage');
1344 break;
1345 case 3:
1346 $text = wfMsg('userpage');
1347 break;
1348 case 5:
1349 $text = wfMsg('wikipediapage');
1350 break;
1351 case 7:
1352 $text = wfMsg('imagepage');
1353 break;
1354 default:
1355 $text= wfMsg('articlepage');
1357 } else {
1359 $lns = Namespace::getTalk( $tns );
1360 $text=$tp;
1362 $n = $wgLang->getNsText( $lns );
1363 if ( '' == $n ) { $link = $pn; }
1364 else { $link = $n.':'.$pn; }
1366 $wgLinkCache->suspend();
1367 $s = $this->makeLink( $link, $text );
1368 $wgLinkCache->resume();
1370 return $s;
1373 function commentLink()
1375 global $wgLang, $wgTitle, $wgLinkCache;
1377 $tns = $wgTitle->getNamespace();
1378 if ( -1 == $tns ) { return ''; }
1380 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1382 # assert Namespace::isTalk( $lns )
1384 $n = $wgLang->getNsText( $lns );
1385 $pn = $wgTitle->getText();
1387 $link = $n.':'.$pn;
1389 $wgLinkCache->suspend();
1390 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit&section=new');
1391 $wgLinkCache->resume();
1393 return $s;
1396 # After all the page content is transformed into HTML, it makes
1397 # a final pass through here for things like table backgrounds.
1399 function transformContent( $text )
1401 return $text;
1404 # Note: This function MUST call getArticleID() on the link,
1405 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1407 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1408 wfProfileIn( 'Skin::makeLink' );
1409 $nt = Title::newFromText( $title );
1410 if ($nt) {
1411 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1412 } else {
1413 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1414 $result = $text == "" ? $title : $text;
1417 wfProfileOut( 'Skin::makeLink' );
1418 return $result;
1421 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1422 $nt = Title::newFromText( $title );
1423 if ($nt) {
1424 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1425 } else {
1426 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1427 return $text == '' ? $title : $text;
1431 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1432 $nt = Title::newFromText( $title );
1433 if ($nt) {
1434 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1435 } else {
1436 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1437 return $text == '' ? $title : $text;
1441 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1442 $nt = Title::newFromText( $title );
1443 if ($nt) {
1444 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1445 } else {
1446 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1447 return $text == '' ? $title : $text;
1451 # Pass a title object, not a title string
1452 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1454 global $wgOut, $wgUser;
1455 $fname = 'Skin::makeLinkObj';
1457 # Fail gracefully
1458 if ( ! isset($nt) )
1459 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1461 if ( $nt->isExternal() ) {
1462 $u = $nt->getFullURL();
1463 $link = $nt->getPrefixedURL();
1464 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1465 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1467 $inside = '';
1468 if ( '' != $trail ) {
1469 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1470 $inside = $m[1];
1471 $trail = $m[2];
1474 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1475 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1476 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1477 } elseif ( ( -1 == $nt->getNamespace() ) ||
1478 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1479 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1480 } else {
1481 if ( $this->postParseLinkColour() ) {
1482 $inside = '';
1483 if ( '' != $trail ) {
1484 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1485 $inside = $m[1];
1486 $trail = $m[2];
1490 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1491 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1492 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1493 } else {
1494 # Work out link colour immediately
1495 $aid = $nt->getArticleID() ;
1496 if ( 0 == $aid ) {
1497 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1498 } else {
1499 $threshold = $wgUser->getOption('stubthreshold') ;
1500 if ( $threshold > 0 ) {
1501 $dbr =& wfGetDB( DB_SLAVE );
1502 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1503 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1504 if ( $s !== false ) {
1505 $size = $s->x;
1506 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1507 $size = $threshold*2 ; # Really big
1509 $dbr->freeResult( $res );
1510 } else {
1511 $size = $threshold*2 ; # Really big
1513 } else {
1514 $size = 1 ;
1516 if ( $size < $threshold ) {
1517 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1518 } else {
1519 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1524 return $retVal;
1527 # Pass a title object, not a title string
1528 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1530 global $wgOut, $wgTitle, $wgInputEncoding;
1532 $fname = 'Skin::makeKnownLinkObj';
1533 wfProfileIn( $fname );
1535 if ( !is_object( $nt ) ) {
1536 return $text;
1538 $link = $nt->getPrefixedURL();
1540 if ( '' == $link ) {
1541 $u = '';
1542 if ( '' == $text ) {
1543 $text = htmlspecialchars( $nt->getFragment() );
1545 } else {
1546 $u = $nt->escapeLocalURL( $query );
1548 if ( '' != $nt->getFragment() ) {
1549 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT, $wgInputEncoding ) );
1550 $replacearray = array(
1551 '%3A' => ':',
1552 '%' => '.'
1554 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1556 if ( '' == $text ) {
1557 $text = htmlspecialchars( $nt->getPrefixedText() );
1559 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1561 $inside = '';
1562 if ( '' != $trail ) {
1563 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1564 $inside = $m[1];
1565 $trail = $m[2];
1568 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1569 wfProfileOut( $fname );
1570 return $r;
1573 # Pass a title object, not a title string
1574 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1576 global $wgOut, $wgUser;
1578 $fname = 'Skin::makeBrokenLinkObj';
1579 wfProfileIn( $fname );
1581 if ( '' == $query ) {
1582 $q = 'action=edit';
1583 } else {
1584 $q = 'action=edit&'.$query;
1586 $u = $nt->escapeLocalURL( $q );
1588 if ( '' == $text ) {
1589 $text = htmlspecialchars( $nt->getPrefixedText() );
1591 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1593 $inside = '';
1594 if ( '' != $trail ) {
1595 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1596 $inside = $m[1];
1597 $trail = $m[2];
1600 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1601 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1602 } else {
1603 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1606 wfProfileOut( $fname );
1607 return $s;
1610 # Pass a title object, not a title string
1611 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1613 global $wgOut, $wgUser;
1615 $link = $nt->getPrefixedURL();
1617 $u = $nt->escapeLocalURL( $query );
1619 if ( '' == $text ) {
1620 $text = htmlspecialchars( $nt->getPrefixedText() );
1622 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1624 $inside = '';
1625 if ( '' != $trail ) {
1626 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1627 $inside = $m[1];
1628 $trail = $m[2];
1631 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1632 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1633 } else {
1634 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1636 return $s;
1639 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1641 $u = $nt->escapeLocalURL( $query );
1642 if ( '' == $text ) {
1643 $text = htmlspecialchars( $nt->getPrefixedText() );
1645 $inside = '';
1646 if ( '' != $trail ) {
1647 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1648 $inside = $m[1];
1649 $trail = $m[2];
1652 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1655 /* these are used extensively in SkinPHPTal, but also some other places */
1656 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1657 $title = Title::makeTitle( NS_SPECIAL, $name );
1658 $this->checkTitle($title, $name);
1659 return $title->getLocalURL( $urlaction );
1661 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1662 $title = Title::newFromText( $name );
1663 $title = $title->getTalkPage();
1664 $this->checkTitle($title, $name);
1665 return $title->getLocalURL( $urlaction );
1667 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1668 $title = Title::newFromText( $name );
1669 $title= $title->getSubjectPage();
1670 $this->checkTitle($title, $name);
1671 return $title->getLocalURL( $urlaction );
1673 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1674 $title = Title::newFromText( wfMsg($name) );
1675 $this->checkTitle($title, $name);
1676 return $title->getLocalURL( $urlaction );
1678 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1679 $title = Title::newFromText( $name );
1680 $this->checkTitle($title, $name);
1681 return $title->getLocalURL( $urlaction );
1683 # this can be passed the NS number as defined in Language.php
1684 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1685 $title = Title::makeTitle( $namespace, $name );
1686 $this->checkTitle($title, $name);
1687 return $title->getLocalURL( $urlaction );
1690 /* these return an array with the 'href' and boolean 'exists' */
1691 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1692 $title = Title::newFromText( $name );
1693 $this->checkTitle($title, $name);
1694 return array(
1695 'href' => $title->getLocalURL( $urlaction ),
1696 'exists' => $title->getArticleID() != 0?true:false
1699 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1700 $title = Title::newFromText( $name );
1701 $title = $title->getTalkPage();
1702 $this->checkTitle($title, $name);
1703 return array(
1704 'href' => $title->getLocalURL( $urlaction ),
1705 'exists' => $title->getArticleID() != 0?true:false
1708 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1709 $title = Title::newFromText( $name );
1710 $title= $title->getSubjectPage();
1711 $this->checkTitle($title, $name);
1712 return array(
1713 'href' => $title->getLocalURL( $urlaction ),
1714 'exists' => $title->getArticleID() != 0?true:false
1717 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1718 $title = Title::newFromText( wfMsg($name) );
1719 $this->checkTitle($title, $name);
1720 return array(
1721 'href' => $title->getLocalURL( $urlaction ),
1722 'exists' => $title->getArticleID() != 0?true:false
1726 # make sure we have some title to operate on
1727 /*static*/ function checkTitle ( &$title, &$name ) {
1728 if(!is_object($title)) {
1729 $title = Title::newFromText( $name );
1730 if(!is_object($title)) {
1731 $title = Title::newFromText( '--error: link target missing--' );
1736 function fnamePart( $url )
1738 $basename = strrchr( $url, '/' );
1739 if ( false === $basename ) { $basename = $url; }
1740 else { $basename = substr( $basename, 1 ); }
1741 return wfEscapeHTML( $basename );
1744 function makeImage( $url, $alt = '' )
1746 global $wgOut;
1748 if ( '' == $alt ) { $alt = $this->fnamePart( $url ); }
1749 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1750 return $s;
1753 function makeImageLink( $name, $url, $alt = '' ) {
1754 $nt = Title::makeTitle( Namespace::getImage(), $name );
1755 return $this->makeImageLinkObj( $nt, $alt );
1758 function makeImageLinkObj( $nt, $alt = '' ) {
1759 global $wgLang, $wgUseImageResize;
1760 $img = Image::newFromTitle( $nt );
1761 $url = $img->getURL();
1763 $align = '';
1764 $prefix = $postfix = '';
1766 if ( $wgUseImageResize ) {
1767 # Check if the alt text is of the form "options|alt text"
1768 # Options are:
1769 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1770 # * left no resizing, just left align. label is used for alt= only
1771 # * right same, but right aligned
1772 # * none same, but not aligned
1773 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1774 # * center center the image
1775 # * framed Keep original image size, no magnify-button.
1777 $part = explode( '|', $alt);
1779 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1780 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1781 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1782 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1783 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1784 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1785 $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
1786 $alt = $part[count($part)-1];
1788 $height = $framed = $thumb = false;
1789 $manual_thumb = "" ;
1791 foreach( $part as $key => $val ) {
1792 $val_parts = explode ( "=" , $val , 2 ) ;
1793 $left_part = array_shift ( $val_parts ) ;
1794 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1795 $thumb=true;
1796 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1797 # use manually specified thumbnail
1798 $thumb=true;
1799 $manual_thumb = array_shift ( $val_parts ) ;
1800 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1801 # remember to set an alignment, don't render immediately
1802 $align = 'right';
1803 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1804 # remember to set an alignment, don't render immediately
1805 $align = 'left';
1806 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1807 # remember to set an alignment, don't render immediately
1808 $align = 'center';
1809 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1810 # remember to set an alignment, don't render immediately
1811 $align = 'none';
1812 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1813 # $match is the image width in pixels
1814 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1815 $width = intval( $m[1] );
1816 $height = intval( $m[2] );
1817 } else {
1818 $width = intval($match);
1820 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1821 $framed=true;
1824 if ( 'center' == $align )
1826 $prefix = '<span style="text-align: center">';
1827 $postfix = '</span>';
1828 $align = 'none';
1831 if ( $thumb || $framed ) {
1833 # Create a thumbnail. Alignment depends on language
1834 # writing direction, # right aligned for left-to-right-
1835 # languages ("Western languages"), left-aligned
1836 # for right-to-left-languages ("Semitic languages")
1838 # If thumbnail width has not been provided, it is set
1839 # here to 180 pixels
1840 if ( $align == '' ) {
1841 $align = $wgLang->isRTL() ? 'left' : 'right';
1843 if ( ! isset($width) ) {
1844 $width = 180;
1846 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1848 } elseif ( isset($width) ) {
1850 # Create a resized image, without the additional thumbnail
1851 # features
1853 if ( ( ! $height === false )
1854 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1855 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1856 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1857 $width = $img->getWidth() * $height / $img->getHeight();
1859 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1861 } # endif $wgUseImageResize
1863 if ( empty( $alt ) ) {
1864 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1866 $alt = htmlspecialchars( $alt );
1868 $u = $nt->escapeLocalURL();
1869 if ( $url == '' )
1871 $s = wfMsg( 'missingimage', $img->getName() );
1872 $s .= "<br>{$alt}<br>{$url}<br>\n";
1873 } else {
1874 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1875 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1877 if ( '' != $align ) {
1878 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1880 return str_replace("\n", ' ',$prefix.$s.$postfix);
1883 # Make HTML for a thumbnail including image, border and caption
1884 # $img is an Image object
1885 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1886 global $wgStylePath, $wgLang;
1887 # $image = Title::makeTitle( Namespace::getImage(), $name );
1888 $url = $img->getURL();
1890 #$label = htmlspecialchars( $label );
1891 $alt = preg_replace( '/<[^>]*>/', '', $label);
1892 $alt = htmlspecialchars( $alt );
1894 if ( $img->exists() )
1896 $width = $img->getWidth();
1897 $height = $img->getHeight();
1898 } else {
1899 $width = $height = 200;
1901 if ( $framed )
1903 // Use image dimensions, don't scale
1904 $boxwidth = $width;
1905 $oboxwidth = $boxwidth + 2;
1906 $boxheight = $height;
1907 $thumbUrl = $url;
1908 } else {
1909 $h = intval( $height/($width/$boxwidth) );
1910 $oboxwidth = $boxwidth + 2;
1911 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1913 $boxwidth *= $boxheight/$h;
1914 } else {
1915 $boxheight = $h;
1917 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1920 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1922 $manual_title = Title::makeTitle( Namespace::getImage(), $manual_thumb ); #new Title ( $manual_thumb ) ;
1923 $manual_img = Image::newFromTitle( $manual_title );
1924 $thumbUrl = $manual_img->getURL();
1925 if ( $manual_img->exists() )
1927 $width = $manual_img->getWidth();
1928 $height = $manual_img->getHeight();
1929 $boxwidth = $width ;
1930 $boxheight = $height ;
1931 $oboxwidth = $boxwidth + 2 ;
1935 $u = $img->getEscapeLocalURL();
1937 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1938 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1939 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1941 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1942 if ( $thumbUrl == '' ) {
1943 $s .= wfMsg( 'missingimage', $img->getName() );
1944 $zoomicon = '';
1945 } else {
1946 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1947 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1948 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1949 if ( $framed ) {
1950 $zoomicon="";
1951 } else {
1952 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1953 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1954 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1955 'width="15" height="11" alt="'.$more.'" /></a></div>';
1958 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1959 return str_replace("\n", ' ', $s);
1962 function makeMediaLink( $name, $url, $alt = "" ) {
1963 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1964 return $this->makeMediaLinkObj( $nt, $alt );
1967 function makeMediaLinkObj( $nt, $alt = "" )
1969 if ( ! isset( $nt ) )
1971 ### HOTFIX. Instead of breaking, return empty string.
1972 $s = $alt;
1973 } else {
1974 $name = $nt->getDBKey();
1975 $url = Image::wfImageUrl( $name );
1976 if ( empty( $alt ) ) {
1977 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1980 $u = htmlspecialchars( $url );
1981 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1983 return $s;
1986 function specialLink( $name, $key = "" )
1988 global $wgLang;
1990 if ( '' == $key ) { $key = strtolower( $name ); }
1991 $pn = $wgLang->ucfirst( $name );
1992 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1993 wfMsg( $key ) );
1996 function makeExternalLink( $url, $text, $escape = true ) {
1997 $style = $this->getExternalLinkAttributes( $url, $text );
1998 $url = htmlspecialchars( $url );
1999 if( $escape ) {
2000 $text = htmlspecialchars( $text );
2002 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2005 # Called by history lists and recent changes
2008 # Returns text for the start of the tabular part of RC
2009 function beginRecentChangesList()
2011 $this->rc_cache = array() ;
2012 $this->rcMoveIndex = 0;
2013 $this->rcCacheIndex = 0 ;
2014 $this->lastdate = '';
2015 $this->rclistOpen = false;
2016 return '';
2019 function beginImageHistoryList()
2021 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2022 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2023 return $s;
2026 # Returns text for the end of RC
2027 # If enhanced RC is in use, returns pretty much all the text
2028 function endRecentChangesList()
2030 $s = $this->recentChangesBlock() ;
2031 if( $this->rclistOpen ) {
2032 $s .= "</ul>\n";
2034 return $s;
2037 # Enhanced RC ungrouped line
2038 function recentChangesBlockLine ( $rcObj )
2040 global $wgStylePath, $wgLang ;
2042 # Get rc_xxxx variables
2043 extract( $rcObj->mAttribs ) ;
2044 $curIdEq = 'curid='.$rc_cur_id;
2046 # Spacer image
2047 $r = '' ;
2049 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2050 $r .= '<tt>' ;
2052 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2053 $r .= '&nbsp;&nbsp;';
2054 } else {
2055 # M & N (minor & new)
2056 $M = wfMsg( 'minoreditletter' );
2057 $N = wfMsg( 'newpageletter' );
2059 if ( $rc_type == RC_NEW ) {
2060 $r .= $N ;
2061 } else {
2062 $r .= '&nbsp;' ;
2064 if ( $rc_minor ) {
2065 $r .= $M ;
2066 } else {
2067 $r .= '&nbsp;' ;
2071 # Timestamp
2072 $r .= ' '.$rcObj->timestamp.' ' ;
2073 $r .= '</tt>' ;
2075 # Article link
2076 $link = $rcObj->link ;
2077 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2078 $r .= $link ;
2080 # Diff
2081 $r .= ' (' ;
2082 $r .= $rcObj->difflink ;
2083 $r .= '; ' ;
2085 # Hist
2086 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2088 # User/talk
2089 $r .= ') . . '.$rcObj->userlink ;
2090 $r .= $rcObj->usertalklink ;
2092 # Comment
2093 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2094 $rc_comment=$this->formatComment($rc_comment);
2095 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2098 $r .= "<br />\n" ;
2099 return $r ;
2102 # Enhanced RC group
2103 function recentChangesBlockGroup ( $block )
2105 global $wgStylePath, $wgLang ;
2107 $r = '' ;
2108 $M = wfMsg( 'minoreditletter' );
2109 $N = wfMsg( 'newpageletter' );
2111 # Collate list of users
2112 $isnew = false ;
2113 $userlinks = array () ;
2114 foreach ( $block AS $rcObj ) {
2115 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2116 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2117 $u = $rcObj->userlink ;
2118 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2119 $userlinks[$u]++ ;
2122 # Sort the list and convert to text
2123 krsort ( $userlinks ) ;
2124 asort ( $userlinks ) ;
2125 $users = array () ;
2126 foreach ( $userlinks as $userlink => $count) {
2127 $text = $userlink ;
2128 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2129 array_push ( $users , $text ) ;
2131 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2133 # Arrow
2134 $rci = 'RCI'.$this->rcCacheIndex ;
2135 $rcl = 'RCL'.$this->rcCacheIndex ;
2136 $rcm = 'RCM'.$this->rcCacheIndex ;
2137 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2138 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2139 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2140 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2141 $r .= $tl ;
2143 # Main line
2144 # M/N
2145 $r .= '<tt>' ;
2146 if ( $isnew ) $r .= $N ;
2147 else $r .= '&nbsp;' ;
2148 $r .= '&nbsp;' ; # Minor
2150 # Timestamp
2151 $r .= ' '.$block[0]->timestamp.' ' ;
2152 $r .= '</tt>' ;
2154 # Article link
2155 $link = $block[0]->link ;
2156 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2157 $r .= $link ;
2159 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2160 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2161 # Changes
2162 $r .= ' ('.count($block).' ' ;
2163 if ( $isnew ) $r .= wfMsg('changes');
2164 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2165 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2166 $r .= '; ' ;
2168 # History
2169 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2170 $r .= ')' ;
2173 $r .= $users ;
2174 $r .= "<br />\n" ;
2176 # Sub-entries
2177 $r .= '<div id="'.$rci.'" style="display:none">' ;
2178 foreach ( $block AS $rcObj ) {
2179 # Get rc_xxxx variables
2180 extract( $rcObj->mAttribs );
2182 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2183 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2184 if ( $rc_new ) $r .= $N ;
2185 else $r .= '&nbsp;' ;
2186 if ( $rc_minor ) $r .= $M ;
2187 else $r .= '&nbsp;' ;
2188 $r .= '</tt>' ;
2190 $o = '' ;
2191 if ( $rc_last_oldid != 0 ) {
2192 $o = 'oldid='.$rc_last_oldid ;
2194 if ( $rc_type == RC_LOG ) {
2195 $link = $rcObj->timestamp ;
2196 } else {
2197 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2199 $link = '<tt>'.$link.'</tt>' ;
2201 $r .= $link ;
2202 $r .= ' (' ;
2203 $r .= $rcObj->curlink ;
2204 $r .= '; ' ;
2205 $r .= $rcObj->lastlink ;
2206 $r .= ') . . '.$rcObj->userlink ;
2207 $r .= $rcObj->usertalklink ;
2208 if ( $rc_comment != '' ) {
2209 $rc_comment=$this->formatComment($rc_comment);
2210 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2212 $r .= "<br />\n" ;
2214 $r .= "</div>\n" ;
2216 $this->rcCacheIndex++ ;
2217 return $r ;
2220 # If enhanced RC is in use, this function takes the previously cached
2221 # RC lines, arranges them, and outputs the HTML
2222 function recentChangesBlock ()
2224 global $wgStylePath ;
2225 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2226 $blockOut = '';
2227 foreach ( $this->rc_cache AS $secureName => $block ) {
2228 if ( count ( $block ) < 2 ) {
2229 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2230 } else {
2231 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2235 return '<div>'.$blockOut.'</div>' ;
2238 # Called in a loop over all displayed RC entries
2239 # Either returns the line, or caches it for later use
2240 function recentChangesLine( &$rc, $watched = false )
2242 global $wgUser ;
2243 $usenew = $wgUser->getOption( 'usenewrc' );
2244 if ( $usenew )
2245 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2246 else
2247 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2248 return $line ;
2251 function recentChangesLineOld( &$rc, $watched = false )
2253 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2255 # Extract DB fields into local scope
2256 extract( $rc->mAttribs );
2257 $curIdEq = 'curid=' . $rc_cur_id;
2259 # Make date header if necessary
2260 $date = $wgLang->date( $rc_timestamp, true);
2261 $s = '';
2262 if ( $date != $this->lastdate ) {
2263 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2264 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2265 $this->lastdate = $date;
2266 $this->rclistOpen = true;
2269 # If this edit has not yet been patrolled, make it stick out
2270 $s .= ( ! $wgUseRCPatrol || $rc_patrolled ) ? '<li> ' : '<li class="not_patrolled"> ';
2272 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2273 # Diff
2274 $s .= '(' . wfMsg( 'diff' ) . ') (';
2275 # Hist
2276 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2277 ') . . ';
2279 # "[[x]] moved to [[y]]"
2280 $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
2281 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2282 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2283 } else {
2284 # Diff link
2285 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2286 $diffLink = wfMsg( 'diff' );
2287 } else {
2288 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2289 ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2290 $rcidparam = "&rcid={$rc_id}";
2291 else
2292 $rcidparam = "";
2293 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2294 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2295 '', '', ' tabindex="'.$rc->counter.'"');
2297 $s .= '('.$diffLink.') (';
2299 # History link
2300 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2301 $s .= ') . . ';
2303 # M and N (minor and new)
2304 $M = wfMsg( 'minoreditletter' );
2305 $N = wfMsg( 'newpageletter' );
2306 if ( $rc_minor ) { $s .= ' <strong>'.$M.'</strong>'; }
2307 if ( $rc_type == RC_NEW ) { $s .= '<strong>'.$N.'</strong>'; }
2309 # Article link
2310 # If it's a new article, there is no diff link, but if it hasn't been
2311 # patrolled yet, we need to give users a way to do so
2312 if ( $wgUseRCPatrol && $rc_type == RC_NEW && $rc_patrolled == 0 &&
2313 $wgUser->getID() != 0 && ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2314 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2315 else
2316 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2318 if ( $watched ) {
2319 $articleLink = '<strong>'.$articleLink.'</strong>';
2321 $s .= ' '.$articleLink;
2325 # Timestamp
2326 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2328 # User link (or contributions for unregistered users)
2329 if ( 0 == $rc_user ) {
2330 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2331 $rc_user_text, 'target=' . $rc_user_text );
2332 } else {
2333 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2335 $s .= $userLink;
2337 # User talk link
2338 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2339 global $wgDisableAnonTalk;
2340 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2341 $userTalkLink = '';
2342 } else {
2343 $utns=$wgLang->getNsText(NS_USER_TALK);
2344 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2346 # Block link
2347 $blockLink='';
2348 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2349 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2350 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2353 if($blockLink) {
2354 if($userTalkLink) $userTalkLink .= ' | ';
2355 $userTalkLink .= $blockLink;
2357 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2359 # Add comment
2360 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2361 $rc_comment=$this->formatComment($rc_comment);
2362 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2364 $s .= "</li>\n";
2366 return $s;
2369 function recentChangesLineNew( &$baseRC, $watched = false )
2371 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2373 # Create a specialised object
2374 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2376 # Extract fields from DB into the function scope (rc_xxxx variables)
2377 extract( $rc->mAttribs );
2378 $curIdEq = 'curid=' . $rc_cur_id;
2380 # If it's a new day, add the headline and flush the cache
2381 $date = $wgLang->date( $rc_timestamp, true);
2382 $ret = '';
2383 if ( $date != $this->lastdate ) {
2384 # Process current cache
2385 $ret = $this->recentChangesBlock () ;
2386 $this->rc_cache = array() ;
2387 $ret .= "<h4>{$date}</h4>\n";
2388 $this->lastdate = $date;
2391 # Make article link
2392 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2393 $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
2394 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2395 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2396 } else {
2397 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2400 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2401 $rc->watched = $watched ;
2402 $rc->link = $clink ;
2403 $rc->timestamp = $time;
2405 # Make "cur" and "diff" links
2406 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2407 $curLink = wfMsg( 'cur' );
2408 $diffLink = wfMsg( 'diff' );
2409 } else {
2410 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2411 $aprops = ' tabindex="'.$baseRC->counter.'"';
2412 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2413 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2416 # Make "last" link
2417 $titleObj = $rc->getTitle();
2418 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2419 $lastLink = wfMsg( 'last' );
2420 } else {
2421 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2422 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2425 # Make user link (or user contributions for unregistered users)
2426 if ( $rc_user == 0 ) {
2427 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2428 $rc_user_text, 'target=' . $rc_user_text );
2429 } else {
2430 $userLink = $this->makeLink( $wgLang->getNsText(
2431 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2434 $rc->userlink = $userLink;
2435 $rc->lastlink = $lastLink;
2436 $rc->curlink = $curLink;
2437 $rc->difflink = $diffLink;
2439 # Make user talk link
2440 $utns=$wgLang->getNsText(NS_USER_TALK);
2441 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2442 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2444 global $wgDisableAnonTalk;
2445 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2446 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2447 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2448 if( $wgDisableAnonTalk )
2449 $rc->usertalklink = ' ('.$blockLink.')';
2450 else
2451 $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
2452 } else {
2453 if( $wgDisableAnonTalk && ($rc_user == 0) )
2454 $rc->usertalklink = '';
2455 else
2456 $rc->usertalklink = ' ('.$userTalkLink.')';
2459 # Put accumulated information into the cache, for later display
2460 # Page moves go on their own line
2461 $title = $rc->getTitle();
2462 $secureName = $title->getPrefixedDBkey();
2463 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2464 # Use an @ character to prevent collision with page names
2465 $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
2466 } else {
2467 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2468 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2470 return $ret;
2473 function endImageHistoryList()
2475 $s = "</ul>\n";
2476 return $s;
2479 /* This function is called by all recent changes variants, by the page history,
2480 and by the user contributions list. It is responsible for formatting edit
2481 comments. It escapes any HTML in the comment, but adds some CSS to format
2482 auto-generated comments (from section editing) and formats [[wikilinks]].
2483 Main author: Erik Möller (moeller@scireview.de)
2485 function formatComment($comment)
2487 global $wgLang;
2488 $comment=wfEscapeHTML($comment);
2490 # The pattern for autogen comments is / * foo * /, which makes for
2491 # some nasty regex.
2492 # We look for all comments, match any text before and after the comment,
2493 # add a separator where needed and format the comment itself with CSS
2494 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2495 $pre=$match[1];
2496 $auto=$match[2];
2497 $post=$match[3];
2498 $sep='-';
2499 if($pre) { $auto = $sep.' '.$auto; }
2500 if($post) { $auto .= ' '.$sep; }
2501 $auto='<span class="autocomment">'.$auto.'</span>';
2502 $comment=$pre.$auto.$post;
2505 # format regular and media links - all other wiki formatting
2506 # is ignored
2507 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2508 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2509 # Handle link renaming [[foo|text]] will show link as "text"
2510 if( "" != $match[3] ) {
2511 $text = $match[3];
2512 } else {
2513 $text = $match[1];
2515 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2516 # Media link; trail not supported.
2517 $linkRegexp = '/\[\[(.*?)\]\]/';
2518 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2519 } else {
2520 # Other kind of link
2521 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2522 $trail = $submatch[1];
2523 } else {
2524 $trail = "";
2526 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2527 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2529 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2531 return $comment;
2534 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2536 global $wgUser, $wgLang, $wgTitle;
2538 $datetime = $wgLang->timeanddate( $timestamp, true );
2539 $del = wfMsg( 'deleteimg' );
2540 $delall = wfMsg( 'deleteimgcompletely' );
2541 $cur = wfMsg( 'cur' );
2543 if ( $iscur ) {
2544 $url = Image::wfImageUrl( $img );
2545 $rlink = $cur;
2546 if ( $wgUser->isSysop() ) {
2547 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2548 '&action=delete' );
2549 $style = $this->getInternalLinkAttributes( $link, $delall );
2551 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2552 } else {
2553 $dlink = $del;
2555 } else {
2556 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
2557 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2558 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2559 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2560 urlencode( $img ) );
2561 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2562 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2563 } else {
2564 # Having live active links for non-logged in users
2565 # means that bots and spiders crawling our site can
2566 # inadvertently change content. Baaaad idea.
2567 $rlink = wfMsg( 'revertimg' );
2568 $dlink = $del;
2571 if ( 0 == $user ) {
2572 $userlink = $usertext;
2573 } else {
2574 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2575 ':'.$usertext, $usertext );
2577 $nbytes = wfMsg( 'nbytes', $size );
2578 $style = $this->getInternalLinkAttributes( $url, $datetime );
2580 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2581 . " . . {$userlink} ({$nbytes})";
2583 if ( '' != $description && '*' != $description ) {
2584 $sk=$wgUser->getSkin();
2585 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2587 $s .= "</li>\n";
2588 return $s;
2591 function tocIndent($level) {
2592 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2595 function tocUnindent($level) {
2596 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2599 # parameter level defines if we are on an indentation level
2600 function tocLine( $anchor, $tocline, $level ) {
2601 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2602 if($level) {
2603 return $link."\n";
2604 } else {
2605 return '<div class="tocline">'.$link."</div>\n";
2610 function tocTable($toc) {
2611 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2612 # try min-width & co when somebody gets a chance
2613 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2614 return
2615 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2616 '<b>'.wfMsg('toc').'</b>' .
2617 $hideline .
2618 '</td></tr><tr id="tocinside"><td>'."\n".
2619 $toc."</td></tr></table>\n";
2622 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2623 function editSectionScript( $section, $head ) {
2624 global $wgTitle, $wgRequest;
2625 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2626 return $head;
2628 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2629 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2632 function editSectionLink( $section ) {
2633 global $wgRequest;
2634 global $wgTitle, $wgUser, $wgLang;
2636 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2637 # Section edit links would be out of sync on an old page.
2638 # But, if we're diffing to the current page, they'll be
2639 # correct.
2640 return '';
2643 $editurl = '&section='.$section;
2644 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2646 if( $wgLang->isRTL() ) {
2647 $farside = 'left';
2648 $nearside = 'right';
2649 } else {
2650 $farside = 'right';
2651 $nearside = 'left';
2653 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2657 // This function is called by EditPage.php and shows a bulletin board style
2658 // toolbar for common editing functions. It can be disabled in the user preferences.
2659 // The necsesary JavaScript code can be found in style/wikibits.js.
2660 function getEditToolbar() {
2661 global $wgStylePath, $wgLang, $wgMimeType;
2663 // toolarray an array of arrays which each include the filename of
2664 // the button image (without path), the opening tag, the closing tag,
2665 // and optionally a sample text that is inserted between the two when no
2666 // selection is highlighted.
2667 // The tip text is shown when the user moves the mouse over the button.
2669 // Already here are accesskeys (key), which are not used yet until someone
2670 // can figure out a way to make them work in IE. However, we should make
2671 // sure these keys are not defined on the edit page.
2672 $toolarray=array(
2673 array( 'image'=>'button_bold.png',
2674 'open'=>"\'\'\'",
2675 'close'=>"\'\'\'",
2676 'sample'=>wfMsg('bold_sample'),
2677 'tip'=>wfMsg('bold_tip'),
2678 'key'=>'B'
2680 array( "image"=>"button_italic.png",
2681 "open"=>"\'\'",
2682 "close"=>"\'\'",
2683 "sample"=>wfMsg("italic_sample"),
2684 "tip"=>wfMsg("italic_tip"),
2685 "key"=>"I"
2687 array( "image"=>"button_link.png",
2688 "open"=>"[[",
2689 "close"=>"]]",
2690 "sample"=>wfMsg("link_sample"),
2691 "tip"=>wfMsg("link_tip"),
2692 "key"=>"L"
2694 array( "image"=>"button_extlink.png",
2695 "open"=>"[",
2696 "close"=>"]",
2697 "sample"=>wfMsg("extlink_sample"),
2698 "tip"=>wfMsg("extlink_tip"),
2699 "key"=>"X"
2701 array( "image"=>"button_headline.png",
2702 "open"=>"\\n== ",
2703 "close"=>" ==\\n",
2704 "sample"=>wfMsg("headline_sample"),
2705 "tip"=>wfMsg("headline_tip"),
2706 "key"=>"H"
2708 array( "image"=>"button_image.png",
2709 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2710 "close"=>"]]",
2711 "sample"=>wfMsg("image_sample"),
2712 "tip"=>wfMsg("image_tip"),
2713 "key"=>"D"
2715 array( "image"=>"button_media.png",
2716 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2717 "close"=>"]]",
2718 "sample"=>wfMsg("media_sample"),
2719 "tip"=>wfMsg("media_tip"),
2720 "key"=>"M"
2722 array( "image"=>"button_math.png",
2723 "open"=>"\\<math\\>",
2724 "close"=>"\\</math\\>",
2725 "sample"=>wfMsg("math_sample"),
2726 "tip"=>wfMsg("math_tip"),
2727 "key"=>"C"
2729 array( "image"=>"button_nowiki.png",
2730 "open"=>"\\<nowiki\\>",
2731 "close"=>"\\</nowiki\\>",
2732 "sample"=>wfMsg("nowiki_sample"),
2733 "tip"=>wfMsg("nowiki_tip"),
2734 "key"=>"N"
2736 array( "image"=>"button_sig.png",
2737 "open"=>"--~~~~",
2738 "close"=>"",
2739 "sample"=>"",
2740 "tip"=>wfMsg("sig_tip"),
2741 "key"=>"Y"
2743 array( "image"=>"button_hr.png",
2744 "open"=>"\\n----\\n",
2745 "close"=>"",
2746 "sample"=>"",
2747 "tip"=>wfMsg("hr_tip"),
2748 "key"=>"R"
2751 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2753 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2754 foreach($toolarray as $tool) {
2756 $image=$wgStylePath.'/images/'.$tool['image'];
2757 $open=$tool['open'];
2758 $close=$tool['close'];
2759 $sample = addslashes( $tool['sample'] );
2761 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2762 // Older browsers show a "speedtip" type message only for ALT.
2763 // Ideally these should be different, realistically they
2764 // probably don't need to be.
2765 $tip = addslashes( $tool['tip'] );
2767 #$key = $tool["key"];
2769 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2772 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2773 $toolbar.="document.writeln(\"</div>\");\n";
2775 $toolbar.="/*]]>*/\n</script>";
2776 return $toolbar;