3 # This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
4 if( defined( "MEDIAWIKI" ) ) {
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'
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
;
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
54 var $postParseLinkColour = true;
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() {
77 # Get/set accessor for delayed link colouring
78 function postParseLinkColour( $setting = NULL ) {
79 return wfSetVar( $this->postParseLinkColour
, $setting );
84 global $wgOut, $wgUser;
86 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
87 $q = $wgUser->getOption( 'quickbar' );
88 if ( '' == $q ) { $q = 0; }
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' ) ) );
124 if( $wgRightsPage ) {
125 $copy = Title
::newFromText( $wgRightsPage );
127 $copyright = $copy->getLocalURL();
130 if( !$copyright && $wgRightsUrl ) {
131 $copyright = $wgRightsUrl;
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'" );
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() );
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";
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');
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();
198 # placeholder, returns generated js in monobook
199 function getUserJs() {
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";
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
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";
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' );
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();
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}\"";
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' ) {
299 if ( 1 == $wgUser->getOption( 'hover' ) ) {
300 $r .= " title=\"{$link}\"";
305 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
307 global $wgUser, $wgOut;
309 if ( $broken == 'stub' ) {
310 $r = ' class="stub"';
311 } else if ( $broken == 'yes' ) {
317 if ( 1 == $wgUser->getOption( 'hover' ) ) {
318 $r .= ' title ="' . $nt->getEscapedText() . '"';
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 );
346 $qb = $this->qbSetting();
348 if( $langlinks = $this->otherLanguages() ) {
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";
361 $left = ($qb == 1 ||
$qb == 3);
362 if($wgLang->isRTL()) $left = !$left;
365 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
366 $this->logoText() . '</td>';
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>";
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 );
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() ) )
416 if($wgUseCategoryBrowser) {
419 $s.= $wgTitle->getAllParentCategories($catstack);
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}'> </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() {
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();
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>';
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 );
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
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;
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 ) ) );
574 function printableLink()
576 global $wgOut, $wgFeedClasses, $wgRequest;
578 $baseurl = $_SERVER['REQUEST_URI'];
579 if( strpos( '?', $baseurl ) == false ) {
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>";
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);}
606 function pageSubtitle()
610 $sub = $wgOut->getSubtitle();
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";
621 function subPageSubtitle()
623 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
625 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
626 $ptext=$wgTitle->getPrefixedText();
627 if(preg_match('/\//',$ptext)) {
628 $links = explode('/',$ptext);
631 foreach($links as $link) {
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
640 $subpages .= '< ';
642 $subpages .= $getlink;
651 function nameAndLogin()
653 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
655 $li = $wgLang->specialPage( 'Userlogin' );
656 $lo = $wgLang->specialPage( 'Userlogout' );
659 if ( 0 == $wgUser->getID() ) {
660 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
663 $tl = $this->makeKnownLink( $wgLang->getNsText(
664 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
665 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
667 $s .= $n . ' ('.$tl.')';
669 $s .= wfMsg('notloggedin');
672 $rt = $wgTitle->getPrefixedURL();
673 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
675 } else { $q = "returnto={$rt}"; }
677 $s .= "\n<br />" . $this->makeKnownLink( $li,
678 wfMsg( 'login' ), $q );
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 ) ) );
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' ),
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()
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') . '" /> '
719 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
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();
742 function bottomLinks()
744 global $wgOut, $wgUser, $wgTitle;
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();
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 ''; }
795 if ( !$wgDisableCounters ) {
796 $count = $wgLang->formatNum( $wgArticle->getCount() );
798 $s = wfMsg( 'viewcount', $count );
802 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
803 require_once("Credits.php");
804 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
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';
826 if( $wgRightsPage ) {
827 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
828 } elseif( $wgRightsUrl ) {
829 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
834 $out .= wfMsg( $msg, $link );
838 function getCopyrightIcon() {
839 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
841 if( $wgRightsIcon ) {
842 $icon = htmlspecialchars( $wgRightsIcon );
844 $url = htmlspecialchars( $wgRightsUrl );
845 $out .= '<a href="'.$url.'">';
847 $text = htmlspecialchars( $wgRightsText );
848 $out .= "<img src=\"$icon\" alt='$text' />";
856 function getPoweredBy() {
858 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
859 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
863 function lastModified()
865 global $wgLang, $wgArticle;
867 $timestamp = $wgArticle->getTimestamp();
869 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
870 $s = ' ' . wfMsg( 'lastmodified', $d );
877 function logoText( $align = '' )
879 if ( '' != $align ) { $a = " align='{$align}'"; }
882 $mp = wfMsg( 'mainpage' );
883 $titleObj = Title
::newFromText( $mp );
884 if ( is_object( $titleObj ) ) {
885 $url = $titleObj->escapeLocalURL();
890 $logourl = $this->getLogo();
891 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
897 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
898 global $wgDisableUploads, $wgRemoteUploads;
900 $fname = 'Skin::quickBar';
901 wfProfileIn( $fname );
903 $action = $wgRequest->getText( 'action' );
904 $wpPreview = $wgRequest->getBool( 'wpPreview' );
905 $tns=$wgTitle->getNamespace();
907 $s = "\n<div id='quickbar'>";
908 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
911 $s .= $this->mainPageLink()
912 . $sep . $this->specialLink( 'recentchanges' )
913 . $sep . $this->specialLink( 'randompage' );
914 if ($wgUser->getID()) {
915 $s.= $sep . $this->specialLink( 'watchlist' ) ;
916 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
917 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
920 // only show watchlist link if logged in
921 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
922 $s .= "\n<br /><hr class='sep' />";
923 $articleExists = $wgTitle->getArticleId();
924 if ( $wgOut->isArticle() ||
$action =='edit' ||
$action =='history' ||
$wpPreview) {
925 if($wgOut->isArticle()) {
926 $s .= '<strong>' . $this->editThisPage() . '</strong>';
927 } else { # backlink to the article in edit or history mode
928 if($articleExists){ # no backlink if no article
931 $text = wfMsg('articlepage');
934 $text = wfMsg('viewtalkpage');
937 $text = wfMsg('userpage');
940 $text = wfMsg('viewtalkpage');
943 $text = wfMsg('wikipediapage');
946 $text = wfMsg('viewtalkpage');
949 $text = wfMsg('imagepage');
952 $text = wfMsg('viewtalkpage');
955 $text= wfMsg('articlepage');
958 $link = $wgTitle->getText();
959 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
960 $link = $nstext . ':' . $link ;
963 $s .= $this->makeLink( $link, $text );
964 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
965 # we just throw in a "New page" text to tell the user that he's in edit mode,
966 # and to avoid messing with the separator that is prepended to the next item
967 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
973 if( $tns%2
&& $action!='edit' && !$wpPreview) {
974 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit§ion=new');
978 watching could cause problems in edit mode:
979 if user edits article, then loads "watch this article" in background and then saves
980 article with "Watch this article" checkbox disabled, the article is transparently
981 unwatched. Therefore we do not show the "Watch this page" link in edit mode
983 if ( 0 != $wgUser->getID() && $articleExists) {
984 if($action!='edit' && $action != 'submit' )
986 $s .= $sep . $this->watchThisPage();
988 if ( $wgTitle->userCanEdit() )
989 $s .= $sep . $this->moveThisPage();
991 if ( $wgUser->isSysop() and $articleExists ) {
992 $s .= $sep . $this->deleteThisPage() .
993 $sep . $this->protectThisPage();
995 $s .= $sep . $this->talkLink();
996 if ($articleExists && $action !='history') {
997 $s .= $sep . $this->historyLink();
999 $s.=$sep . $this->whatLinksHere();
1001 if($wgOut->isArticleRelated()) {
1002 $s .= $sep . $this->watchPageLinksLink();
1005 if ( Namespace::getUser() == $wgTitle->getNamespace()
1006 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1009 $id=User
::idFromName($wgTitle->getText());
1010 $ip=User
::isIP($wgTitle->getText());
1013 $s .= $sep . $this->userContribsLink();
1015 if ( 0 != $wgUser->getID() ) {
1016 if($id) { # can only email real users
1017 $s .= $sep . $this->emailUserLink();
1021 $s .= "\n<br /><hr class='sep' />";
1024 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads ||
$wgRemoteUploads ) ) {
1025 $s .= $this->specialLink( 'upload' ) . $sep;
1027 $s .= $this->specialLink( 'specialpages' )
1028 . $sep . $this->bugReportsLink();
1030 global $wgSiteSupportPage;
1031 if( $wgSiteSupportPage ) {
1032 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1033 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1036 $s .= "\n<br /></div>\n";
1037 wfProfileOut( $fname );
1041 function specialPagesList()
1043 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1044 require_once('SpecialPage.php');
1046 $pages = SpecialPage
::getPages();
1048 foreach ( $pages[''] as $name => $page ) {
1049 $a[$name] = $page->getDescription();
1051 if ( $wgUser->isSysop() )
1053 foreach ( $pages['sysop'] as $name => $page ) {
1054 $a[$name] = $page->getDescription();
1057 if ( $wgUser->isDeveloper() )
1059 foreach ( $pages['developer'] as $name => $page ) {
1060 $a[$name] = $page->getDescription() ;
1063 $go = wfMsg( 'go' );
1064 $sp = wfMsg( 'specialpages' );
1065 $spp = $wgLang->specialPage( 'Specialpages' );
1067 $s = '<form id="specialpages" method="get" class="inline" ' .
1068 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1069 $s .= "<select name=\"wpDropdown\">\n";
1070 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1072 foreach ( $a as $name => $desc ) {
1073 $p = $wgLang->specialPage( $name );
1074 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1076 $s .= "</select>\n";
1077 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1082 function mainPageLink()
1084 $mp = wfMsg( 'mainpage' );
1085 $s = $this->makeKnownLink( $mp, $mp );
1089 function copyrightLink()
1091 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1092 wfMsg( 'copyrightpagename' ) );
1096 function aboutLink()
1098 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1099 wfMsg( 'aboutwikipedia' ) );
1104 function disclaimerLink()
1106 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1107 wfMsg( 'disclaimers' ) );
1111 function editThisPage()
1113 global $wgOut, $wgTitle, $wgRequest;
1115 $oldid = $wgRequest->getVal( 'oldid' );
1116 $diff = $wgRequest->getVal( 'diff' );
1117 $redirect = $wgRequest->getVal( 'redirect' );
1119 if ( ! $wgOut->isArticleRelated() ) {
1120 $s = wfMsg( 'protectedpage' );
1122 $n = $wgTitle->getPrefixedText();
1123 if ( $wgTitle->userCanEdit() ) {
1124 $t = wfMsg( 'editthispage' );
1126 #$t = wfMsg( "protectedpage" );
1127 $t = wfMsg( 'viewsource' );
1131 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1132 if ( $oldid && ! isset( $diff ) ) {
1133 $oid = "&oldid={$oldid}";
1135 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1140 function deleteThisPage()
1142 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1144 $diff = $wgRequest->getVal( 'diff' );
1145 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1146 $n = $wgTitle->getPrefixedText();
1147 $t = wfMsg( 'deletethispage' );
1149 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1156 function protectThisPage()
1158 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1160 $diff = $wgRequest->getVal( 'diff' );
1161 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1162 $n = $wgTitle->getPrefixedText();
1164 if ( $wgTitle->isProtected() ) {
1165 $t = wfMsg( 'unprotectthispage' );
1166 $q = 'action=unprotect';
1168 $t = wfMsg( 'protectthispage' );
1169 $q = 'action=protect';
1171 $s = $this->makeKnownLink( $n, $t, $q );
1178 function watchThisPage()
1180 global $wgUser, $wgOut, $wgTitle;
1182 if ( $wgOut->isArticleRelated() ) {
1183 $n = $wgTitle->getPrefixedText();
1185 if ( $wgTitle->userIsWatching() ) {
1186 $t = wfMsg( 'unwatchthispage' );
1187 $q = 'action=unwatch';
1189 $t = wfMsg( 'watchthispage' );
1190 $q = 'action=watch';
1192 $s = $this->makeKnownLink( $n, $t, $q );
1194 $s = wfMsg( 'notanarticle' );
1199 function moveThisPage()
1201 global $wgTitle, $wgLang;
1203 if ( $wgTitle->userCanEdit() ) {
1204 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1205 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1206 } // no message if page is protected - would be redundant
1210 function historyLink()
1214 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1215 wfMsg( 'history' ), 'action=history' );
1219 function whatLinksHere()
1221 global $wgTitle, $wgLang;
1223 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1224 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1228 function userContribsLink()
1230 global $wgTitle, $wgLang;
1232 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1233 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1237 function emailUserLink()
1239 global $wgTitle, $wgLang;
1241 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1242 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1246 function watchPageLinksLink()
1248 global $wgOut, $wgTitle, $wgLang;
1250 if ( ! $wgOut->isArticleRelated() ) {
1251 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1253 $s = $this->makeKnownLink( $wgLang->specialPage(
1254 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1255 'target=' . $wgTitle->getPrefixedURL() );
1260 function otherLanguages()
1262 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1264 $a = $wgOut->getLanguageLinks();
1265 if ( 0 == count( $a ) ) {
1266 if ( !$wgUseNewInterlanguage ) return '';
1267 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1268 if ( $ns != 0 AND $ns != 1 ) return '' ;
1270 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1271 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1272 wfMsg( 'intl' ) , $x );
1275 if ( !$wgUseNewInterlanguage ) {
1276 $s = wfMsg( 'otherlanguages' ) . ': ';
1278 global $wgLanguageCode ;
1279 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1280 $x .= '&xl='.$wgLanguageCode ;
1281 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1282 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1285 $s = wfMsg( 'otherlanguages' ) . ': ';
1287 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1288 foreach( $a as $l ) {
1289 if ( ! $first ) { $s .= ' | '; }
1292 $nt = Title
::newFromText( $l );
1293 $url = $nt->getFullURL();
1294 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1296 if ( '' == $text ) { $text = $l; }
1297 $style = $this->getExternalLinkAttributes( $l, $text );
1298 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1300 if($wgLang->isRTL()) $s .= '</span>';
1304 function bugReportsLink()
1306 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1307 wfMsg( 'bugreports' ) );
1313 global $wgLinkCache;
1314 $t1 = Title
::newFromText( gmdate( 'F j' ) );
1315 $t2 = Title
::newFromText( gmdate( 'Y' ) );
1317 $wgLinkCache->suspend();
1318 $id = $t1->getArticleID();
1319 $wgLinkCache->resume();
1322 $s = $this->makeBrokenLink( $t1->getText() );
1324 $s = $this->makeKnownLink( $t1->getText() );
1328 $wgLinkCache->suspend();
1329 $id = $t2->getArticleID();
1330 $wgLinkCache->resume();
1333 $s .= $this->makeBrokenLink( $t2->getText() );
1335 $s .= $this->makeKnownLink( $t2->getText() );
1342 global $wgLang, $wgTitle, $wgLinkCache;
1344 $tns = $wgTitle->getNamespace();
1345 if ( -1 == $tns ) { return ''; }
1347 $pn = $wgTitle->getText();
1348 $tp = wfMsg( 'talkpage' );
1349 if ( Namespace::isTalk( $tns ) ) {
1350 $lns = Namespace::getSubject( $tns );
1353 $text = wfMsg('articlepage');
1356 $text = wfMsg('userpage');
1359 $text = wfMsg('wikipediapage');
1362 $text = wfMsg('imagepage');
1365 $text= wfMsg('articlepage');
1369 $lns = Namespace::getTalk( $tns );
1372 $n = $wgLang->getNsText( $lns );
1373 if ( '' == $n ) { $link = $pn; }
1374 else { $link = $n.':'.$pn; }
1376 $wgLinkCache->suspend();
1377 $s = $this->makeLink( $link, $text );
1378 $wgLinkCache->resume();
1383 function commentLink()
1385 global $wgLang, $wgTitle, $wgLinkCache;
1387 $tns = $wgTitle->getNamespace();
1388 if ( -1 == $tns ) { return ''; }
1390 $lns = ( Namespace::isTalk( $tns ) ) ?
$tns : Namespace::getTalk( $tns );
1392 # assert Namespace::isTalk( $lns )
1394 $n = $wgLang->getNsText( $lns );
1395 $pn = $wgTitle->getText();
1399 $wgLinkCache->suspend();
1400 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit§ion=new');
1401 $wgLinkCache->resume();
1406 # After all the page content is transformed into HTML, it makes
1407 # a final pass through here for things like table backgrounds.
1409 function transformContent( $text )
1414 # Note: This function MUST call getArticleID() on the link,
1415 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1417 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1418 wfProfileIn( 'Skin::makeLink' );
1419 $nt = Title
::newFromText( $title );
1421 $result = $this->makeLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1423 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1424 $result = $text == "" ?
$title : $text;
1427 wfProfileOut( 'Skin::makeLink' );
1431 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1432 $nt = Title
::newFromText( $title );
1434 return $this->makeKnownLinkObj( Title
::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1436 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1437 return $text == '' ?
$title : $text;
1441 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1442 $nt = Title
::newFromText( $title );
1444 return $this->makeBrokenLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1446 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1447 return $text == '' ?
$title : $text;
1451 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1452 $nt = Title
::newFromText( $title );
1454 return $this->makeStubLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1456 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1457 return $text == '' ?
$title : $text;
1461 # Pass a title object, not a title string
1462 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1464 global $wgOut, $wgUser;
1465 $fname = 'Skin::makeLinkObj';
1469 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1471 if ( $nt->isExternal() ) {
1472 $u = $nt->getFullURL();
1473 $link = $nt->getPrefixedURL();
1474 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1475 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1478 if ( '' != $trail ) {
1479 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1484 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1485 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1486 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1487 } elseif ( ( -1 == $nt->getNamespace() ) ||
1488 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1489 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1491 if ( $this->postParseLinkColour() ) {
1493 if ( '' != $trail ) {
1494 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1500 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1501 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1502 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1504 # Work out link colour immediately
1505 $aid = $nt->getArticleID() ;
1507 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1509 $threshold = $wgUser->getOption('stubthreshold') ;
1510 if ( $threshold > 0 ) {
1511 $dbr =& wfGetDB( DB_SLAVE
);
1512 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1513 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1514 if ( $s !== false ) {
1516 if ( $s->cur_is_redirect
OR $s->cur_namespace
!= 0 ) {
1517 $size = $threshold*2 ; # Really big
1519 $dbr->freeResult( $res );
1521 $size = $threshold*2 ; # Really big
1526 if ( $size < $threshold ) {
1527 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1529 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1537 # Pass a title object, not a title string
1538 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1540 global $wgOut, $wgTitle, $wgInputEncoding;
1542 $fname = 'Skin::makeKnownLinkObj';
1543 wfProfileIn( $fname );
1545 if ( !is_object( $nt ) ) {
1548 $link = $nt->getPrefixedURL();
1550 if ( '' == $link ) {
1552 if ( '' == $text ) {
1553 $text = htmlspecialchars( $nt->getFragment() );
1556 $u = $nt->escapeLocalURL( $query );
1558 if ( '' != $nt->getFragment() ) {
1559 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1560 $replacearray = array(
1564 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1566 if ( '' == $text ) {
1567 $text = htmlspecialchars( $nt->getPrefixedText() );
1569 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1572 if ( '' != $trail ) {
1573 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1578 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1579 wfProfileOut( $fname );
1583 # Pass a title object, not a title string
1584 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1586 global $wgOut, $wgUser;
1590 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1592 $fname = 'Skin::makeBrokenLinkObj';
1593 wfProfileIn( $fname );
1595 if ( '' == $query ) {
1598 $q = 'action=edit&'.$query;
1600 $u = $nt->escapeLocalURL( $q );
1602 if ( '' == $text ) {
1603 $text = htmlspecialchars( $nt->getPrefixedText() );
1605 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1608 if ( '' != $trail ) {
1609 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1614 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1615 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1617 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1620 wfProfileOut( $fname );
1624 # Pass a title object, not a title string
1625 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1627 global $wgOut, $wgUser;
1629 $link = $nt->getPrefixedURL();
1631 $u = $nt->escapeLocalURL( $query );
1633 if ( '' == $text ) {
1634 $text = htmlspecialchars( $nt->getPrefixedText() );
1636 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1639 if ( '' != $trail ) {
1640 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1645 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1646 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1648 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1653 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1655 $u = $nt->escapeLocalURL( $query );
1656 if ( '' == $text ) {
1657 $text = htmlspecialchars( $nt->getPrefixedText() );
1660 if ( '' != $trail ) {
1661 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1666 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1669 /* these are used extensively in SkinPHPTal, but also some other places */
1670 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1671 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1672 $this->checkTitle($title, $name);
1673 return $title->getLocalURL( $urlaction );
1675 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1676 $title = Title
::newFromText( $name );
1677 $title = $title->getTalkPage();
1678 $this->checkTitle($title, $name);
1679 return $title->getLocalURL( $urlaction );
1681 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1682 $title = Title
::newFromText( $name );
1683 $title= $title->getSubjectPage();
1684 $this->checkTitle($title, $name);
1685 return $title->getLocalURL( $urlaction );
1687 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1688 $title = Title
::newFromText( wfMsg($name) );
1689 $this->checkTitle($title, $name);
1690 return $title->getLocalURL( $urlaction );
1692 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1693 $title = Title
::newFromText( $name );
1694 $this->checkTitle($title, $name);
1695 return $title->getLocalURL( $urlaction );
1697 # this can be passed the NS number as defined in Language.php
1698 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1699 $title = Title
::makeTitle( $namespace, $name );
1700 $this->checkTitle($title, $name);
1701 return $title->getLocalURL( $urlaction );
1704 /* these return an array with the 'href' and boolean 'exists' */
1705 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1706 $title = Title
::newFromText( $name );
1707 $this->checkTitle($title, $name);
1709 'href' => $title->getLocalURL( $urlaction ),
1710 'exists' => $title->getArticleID() != 0?
true:false
1713 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1714 $title = Title
::newFromText( $name );
1715 $title = $title->getTalkPage();
1716 $this->checkTitle($title, $name);
1718 'href' => $title->getLocalURL( $urlaction ),
1719 'exists' => $title->getArticleID() != 0?
true:false
1722 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1723 $title = Title
::newFromText( $name );
1724 $title= $title->getSubjectPage();
1725 $this->checkTitle($title, $name);
1727 'href' => $title->getLocalURL( $urlaction ),
1728 'exists' => $title->getArticleID() != 0?
true:false
1731 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1732 $title = Title
::newFromText( wfMsg($name) );
1733 $this->checkTitle($title, $name);
1735 'href' => $title->getLocalURL( $urlaction ),
1736 'exists' => $title->getArticleID() != 0?
true:false
1740 # make sure we have some title to operate on
1741 /*static*/ function checkTitle ( &$title, &$name ) {
1742 if(!is_object($title)) {
1743 $title = Title
::newFromText( $name );
1744 if(!is_object($title)) {
1745 $title = Title
::newFromText( '--error: link target missing--' );
1750 function fnamePart( $url )
1752 $basename = strrchr( $url, '/' );
1753 if ( false === $basename ) {
1756 $basename = substr( $basename, 1 );
1758 return htmlspecialchars( $basename );
1761 function makeImage( $url, $alt = '' )
1766 $alt = $this->fnamePart( $url );
1768 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1772 function makeImageLink( $name, $url, $alt = '' ) {
1773 $nt = Title
::makeTitle( Namespace::getImage(), $name );
1774 return $this->makeImageLinkObj( $nt, $alt );
1777 function makeImageLinkObj( $nt, $alt = '' ) {
1778 global $wgLang, $wgUseImageResize;
1779 $img = Image
::newFromTitle( $nt );
1780 $url = $img->getURL();
1783 $prefix = $postfix = '';
1785 if ( $wgUseImageResize ) {
1786 # Check if the alt text is of the form "options|alt text"
1788 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1789 # * left no resizing, just left align. label is used for alt= only
1790 # * right same, but right aligned
1791 # * none same, but not aligned
1792 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1793 # * center center the image
1794 # * framed Keep original image size, no magnify-button.
1796 $part = explode( '|', $alt);
1798 $mwThumb =& MagicWord
::get( MAG_IMG_THUMBNAIL
);
1799 $mwLeft =& MagicWord
::get( MAG_IMG_LEFT
);
1800 $mwRight =& MagicWord
::get( MAG_IMG_RIGHT
);
1801 $mwNone =& MagicWord
::get( MAG_IMG_NONE
);
1802 $mwWidth =& MagicWord
::get( MAG_IMG_WIDTH
);
1803 $mwCenter =& MagicWord
::get( MAG_IMG_CENTER
);
1804 $mwFramed =& MagicWord
::get( MAG_IMG_FRAMED
);
1805 $alt = $part[count($part)-1];
1807 $height = $framed = $thumb = false;
1808 $manual_thumb = "" ;
1810 foreach( $part as $key => $val ) {
1811 $val_parts = explode ( "=" , $val , 2 ) ;
1812 $left_part = array_shift ( $val_parts ) ;
1813 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1815 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1816 # use manually specified thumbnail
1818 $manual_thumb = array_shift ( $val_parts ) ;
1819 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1820 # remember to set an alignment, don't render immediately
1822 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1823 # remember to set an alignment, don't render immediately
1825 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1826 # remember to set an alignment, don't render immediately
1828 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1829 # remember to set an alignment, don't render immediately
1831 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1832 # $match is the image width in pixels
1833 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1834 $width = intval( $m[1] );
1835 $height = intval( $m[2] );
1837 $width = intval($match);
1839 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1843 if ( 'center' == $align )
1845 $prefix = '<span style="text-align: center">';
1846 $postfix = '</span>';
1850 if ( $thumb ||
$framed ) {
1852 # Create a thumbnail. Alignment depends on language
1853 # writing direction, # right aligned for left-to-right-
1854 # languages ("Western languages"), left-aligned
1855 # for right-to-left-languages ("Semitic languages")
1857 # If thumbnail width has not been provided, it is set
1858 # here to 180 pixels
1859 if ( $align == '' ) {
1860 $align = $wgLang->isRTL() ?
'left' : 'right';
1862 if ( ! isset($width) ) {
1865 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1867 } elseif ( isset($width) ) {
1869 # Create a resized image, without the additional thumbnail
1872 if ( ( ! $height === false )
1873 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1874 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1875 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1876 $width = $img->getWidth() * $height / $img->getHeight();
1878 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1880 } # endif $wgUseImageResize
1882 if ( empty( $alt ) ) {
1883 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1885 $alt = htmlspecialchars( $alt );
1887 $u = $nt->escapeLocalURL();
1890 $s = wfMsg( 'missingimage', $img->getName() );
1891 $s .= "<br>{$alt}<br>{$url}<br>\n";
1893 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1894 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1896 if ( '' != $align ) {
1897 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1899 return str_replace("\n", ' ',$prefix.$s.$postfix);
1902 # Make HTML for a thumbnail including image, border and caption
1903 # $img is an Image object
1904 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1905 global $wgStylePath, $wgLang;
1906 # $image = Title::makeTitle( Namespace::getImage(), $name );
1907 $url = $img->getURL();
1909 #$label = htmlspecialchars( $label );
1910 $alt = preg_replace( '/<[^>]*>/', '', $label);
1911 $alt = htmlspecialchars( $alt );
1913 $width = $height = 0;
1914 if ( $img->exists() )
1916 $width = $img->getWidth();
1917 $height = $img->getHeight();
1919 if ( 0 == $width ||
0 == $height )
1921 $width = $height = 200;
1923 if ( $boxwidth == 0 )
1929 // Use image dimensions, don't scale
1931 $oboxwidth = $boxwidth +
2;
1932 $boxheight = $height;
1935 $h = intval( $height/($width/$boxwidth) );
1936 $oboxwidth = $boxwidth +
2;
1937 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1939 $boxwidth *= $boxheight/$h;
1943 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1946 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1948 $manual_title = Title
::makeTitle( Namespace::getImage(), $manual_thumb ); #new Title ( $manual_thumb ) ;
1949 $manual_img = Image
::newFromTitle( $manual_title );
1950 $thumbUrl = $manual_img->getURL();
1951 if ( $manual_img->exists() )
1953 $width = $manual_img->getWidth();
1954 $height = $manual_img->getHeight();
1955 $boxwidth = $width ;
1956 $boxheight = $height ;
1957 $oboxwidth = $boxwidth +
2 ;
1961 $u = $img->getEscapeLocalURL();
1963 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1964 $magnifyalign = $wgLang->isRTL() ?
'left' : 'right';
1965 $textalign = $wgLang->isRTL() ?
' style="text-align:right"' : '';
1967 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1968 if ( $thumbUrl == '' ) {
1969 $s .= wfMsg( 'missingimage', $img->getName() );
1972 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1973 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1974 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1978 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1979 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1980 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1981 'width="15" height="11" alt="'.$more.'" /></a></div>';
1984 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1985 return str_replace("\n", ' ', $s);
1988 function makeMediaLink( $name, $url, $alt = "" ) {
1989 $nt = Title
::makeTitle( Namespace::getMedia(), $name );
1990 return $this->makeMediaLinkObj( $nt, $alt );
1993 function makeMediaLinkObj( $nt, $alt = "" )
1995 if ( ! isset( $nt ) )
1997 ### HOTFIX. Instead of breaking, return empty string.
2000 $name = $nt->getDBKey();
2001 $url = Image
::wfImageUrl( $name );
2002 if ( empty( $alt ) ) {
2003 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2006 $u = htmlspecialchars( $url );
2007 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2012 function specialLink( $name, $key = "" )
2016 if ( '' == $key ) { $key = strtolower( $name ); }
2017 $pn = $wgLang->ucfirst( $name );
2018 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2022 function makeExternalLink( $url, $text, $escape = true ) {
2023 $style = $this->getExternalLinkAttributes( $url, $text );
2024 $url = htmlspecialchars( $url );
2026 $text = htmlspecialchars( $text );
2028 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2031 # Called by history lists and recent changes
2034 # Returns text for the start of the tabular part of RC
2035 function beginRecentChangesList()
2037 $this->rc_cache
= array() ;
2038 $this->rcMoveIndex
= 0;
2039 $this->rcCacheIndex
= 0 ;
2040 $this->lastdate
= '';
2041 $this->rclistOpen
= false;
2045 function beginImageHistoryList()
2047 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2048 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2052 # Returns text for the end of RC
2053 # If enhanced RC is in use, returns pretty much all the text
2054 function endRecentChangesList()
2056 $s = $this->recentChangesBlock() ;
2057 if( $this->rclistOpen
) {
2063 # Enhanced RC ungrouped line
2064 function recentChangesBlockLine ( $rcObj )
2066 global $wgStylePath, $wgLang ;
2068 # Get rc_xxxx variables
2069 extract( $rcObj->mAttribs
) ;
2070 $curIdEq = 'curid='.$rc_cur_id;
2075 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2078 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2079 $r .= ' ';
2081 # M & N (minor & new)
2082 $M = wfMsg( 'minoreditletter' );
2083 $N = wfMsg( 'newpageletter' );
2085 if ( $rc_type == RC_NEW
) {
2098 $r .= ' '.$rcObj->timestamp
.' ' ;
2102 $link = $rcObj->link
;
2103 if ( $rcObj->watched
) $link = '<strong>'.$link.'</strong>' ;
2108 $r .= $rcObj->difflink
;
2112 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2115 $r .= ') . . '.$rcObj->userlink
;
2116 $r .= $rcObj->usertalklink
;
2119 if ( $rc_comment != '' && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2120 $rc_comment=$this->formatComment($rc_comment);
2121 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2129 function recentChangesBlockGroup ( $block )
2131 global $wgStylePath, $wgLang ;
2134 $M = wfMsg( 'minoreditletter' );
2135 $N = wfMsg( 'newpageletter' );
2137 # Collate list of users
2139 $userlinks = array () ;
2140 foreach ( $block AS $rcObj ) {
2141 $oldid = $rcObj->mAttribs
['rc_last_oldid'];
2142 if ( $rcObj->mAttribs
['rc_new'] ) $isnew = true ;
2143 $u = $rcObj->userlink
;
2144 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2148 # Sort the list and convert to text
2149 krsort ( $userlinks ) ;
2150 asort ( $userlinks ) ;
2152 foreach ( $userlinks as $userlink => $count) {
2154 if ( $count > 1 ) $text .= " ({$count}×)" ;
2155 array_push ( $users , $text ) ;
2157 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2160 $rci = 'RCI'.$this->rcCacheIndex
;
2161 $rcl = 'RCL'.$this->rcCacheIndex
;
2162 $rcm = 'RCM'.$this->rcCacheIndex
;
2163 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2164 $arrowdir = $wgLang->isRTL() ?
'l' : 'r';
2165 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2166 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2172 if ( $isnew ) $r .= $N ;
2173 else $r .= ' ' ;
2174 $r .= ' ' ; # Minor
2177 $r .= ' '.$block[0]->timestamp
.' ' ;
2181 $link = $block[0]->link
;
2182 if ( $block[0]->watched
) $link = '<strong>'.$link.'</strong>' ;
2185 $curIdEq = 'curid=' . $block[0]->mAttribs
['rc_cur_id'];
2186 if ( $block[0]->mAttribs
['rc_type'] != RC_LOG
) {
2188 $r .= ' ('.count($block).' ' ;
2189 if ( $isnew ) $r .= wfMsg('changes');
2190 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2191 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2195 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2203 $r .= '<div id="'.$rci.'" style="display:none">' ;
2204 foreach ( $block AS $rcObj ) {
2205 # Get rc_xxxx variables
2206 extract( $rcObj->mAttribs
);
2208 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2209 $r .= '<tt> ' ;
2210 if ( $rc_new ) $r .= $N ;
2211 else $r .= ' ' ;
2212 if ( $rc_minor ) $r .= $M ;
2213 else $r .= ' ' ;
2217 if ( $rc_last_oldid != 0 ) {
2218 $o = 'oldid='.$rc_last_oldid ;
2220 if ( $rc_type == RC_LOG
) {
2221 $link = $rcObj->timestamp
;
2223 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp
, "{$curIdEq}&$o" ) ;
2225 $link = '<tt>'.$link.'</tt>' ;
2229 $r .= $rcObj->curlink
;
2231 $r .= $rcObj->lastlink
;
2232 $r .= ') . . '.$rcObj->userlink
;
2233 $r .= $rcObj->usertalklink
;
2234 if ( $rc_comment != '' ) {
2235 $rc_comment=$this->formatComment($rc_comment);
2236 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2242 $this->rcCacheIndex++
;
2246 # If enhanced RC is in use, this function takes the previously cached
2247 # RC lines, arranges them, and outputs the HTML
2248 function recentChangesBlock ()
2250 global $wgStylePath ;
2251 if ( count ( $this->rc_cache
) == 0 ) return '' ;
2253 foreach ( $this->rc_cache
AS $secureName => $block ) {
2254 if ( count ( $block ) < 2 ) {
2255 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2257 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2261 return '<div>'.$blockOut.'</div>' ;
2264 # Called in a loop over all displayed RC entries
2265 # Either returns the line, or caches it for later use
2266 function recentChangesLine( &$rc, $watched = false )
2269 $usenew = $wgUser->getOption( 'usenewrc' );
2271 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2273 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2277 function recentChangesLineOld( &$rc, $watched = false )
2279 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2281 # Extract DB fields into local scope
2282 extract( $rc->mAttribs
);
2283 $curIdEq = 'curid=' . $rc_cur_id;
2285 # Make date header if necessary
2286 $date = $wgLang->date( $rc_timestamp, true);
2288 if ( $date != $this->lastdate
) {
2289 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2290 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2291 $this->lastdate
= $date;
2292 $this->rclistOpen
= true;
2295 # If this edit has not yet been patrolled, make it stick out
2296 $s .= ( ! $wgUseRCPatrol ||
$rc_patrolled ) ?
'<li> ' : '<li class="not_patrolled"> ';
2298 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2300 $s .= '(' . wfMsg( 'diff' ) . ') (';
2302 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2305 # "[[x]] moved to [[y]]"
2306 $msg = ( $rc_type == RC_MOVE
) ?
'1movedto2' : '1movedto2_redir';
2307 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2308 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2311 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2312 $diffLink = wfMsg( 'diff' );
2314 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2315 ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2316 $rcidparam = "&rcid={$rc_id}";
2319 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2320 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2321 '', '', ' tabindex="'.$rc->counter
.'"');
2323 $s .= '('.$diffLink.') (';
2326 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2329 # M and N (minor and new)
2330 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2331 if ( $rc_type == RC_NEW
) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2334 # If it's a new article, there is no diff link, but if it hasn't been
2335 # patrolled yet, we need to give users a way to do so
2336 if ( $wgUseRCPatrol && $rc_type == RC_NEW
&& $rc_patrolled == 0 &&
2337 $wgUser->getID() != 0 && ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2338 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2340 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2343 $articleLink = '<strong>'.$articleLink.'</strong>';
2345 $s .= ' '.$articleLink;
2350 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2352 # User link (or contributions for unregistered users)
2353 if ( 0 == $rc_user ) {
2354 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2355 $rc_user_text, 'target=' . $rc_user_text );
2357 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2362 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2363 global $wgDisableAnonTalk;
2364 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2367 $utns=$wgLang->getNsText(NS_USER_TALK
);
2368 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2372 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2373 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2374 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2378 if($userTalkLink) $userTalkLink .= ' | ';
2379 $userTalkLink .= $blockLink;
2381 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2384 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2385 $rc_comment=$this->formatComment($rc_comment);
2386 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2393 function recentChangesLineNew( &$baseRC, $watched = false )
2395 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2397 # Create a specialised object
2398 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2400 # Extract fields from DB into the function scope (rc_xxxx variables)
2401 extract( $rc->mAttribs
);
2402 $curIdEq = 'curid=' . $rc_cur_id;
2404 # If it's a new day, add the headline and flush the cache
2405 $date = $wgLang->date( $rc_timestamp, true);
2407 if ( $date != $this->lastdate
) {
2408 # Process current cache
2409 $ret = $this->recentChangesBlock () ;
2410 $this->rc_cache
= array() ;
2411 $ret .= "<h4>{$date}</h4>\n";
2412 $this->lastdate
= $date;
2416 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2417 $msg = ( $rc_type == RC_MOVE
) ?
"1movedto2" : "1movedto2_redir";
2418 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2419 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2421 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2424 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2425 $rc->watched
= $watched ;
2426 $rc->link
= $clink ;
2427 $rc->timestamp
= $time;
2429 # Make "cur" and "diff" links
2430 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2431 $curLink = wfMsg( 'cur' );
2432 $diffLink = wfMsg( 'diff' );
2434 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2435 $aprops = ' tabindex="'.$baseRC->counter
.'"';
2436 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2437 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2441 $titleObj = $rc->getTitle();
2442 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2443 $lastLink = wfMsg( 'last' );
2445 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2446 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2449 # Make user link (or user contributions for unregistered users)
2450 if ( $rc_user == 0 ) {
2451 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2452 $rc_user_text, 'target=' . $rc_user_text );
2454 $userLink = $this->makeLink( $wgLang->getNsText(
2455 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2458 $rc->userlink
= $userLink;
2459 $rc->lastlink
= $lastLink;
2460 $rc->curlink
= $curLink;
2461 $rc->difflink
= $diffLink;
2463 # Make user talk link
2464 $utns=$wgLang->getNsText(NS_USER_TALK
);
2465 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2466 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2468 global $wgDisableAnonTalk;
2469 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2470 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2471 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2472 if( $wgDisableAnonTalk )
2473 $rc->usertalklink
= ' ('.$blockLink.')';
2475 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2477 if( $wgDisableAnonTalk && ($rc_user == 0) )
2478 $rc->usertalklink
= '';
2480 $rc->usertalklink
= ' ('.$userTalkLink.')';
2483 # Put accumulated information into the cache, for later display
2484 # Page moves go on their own line
2485 $title = $rc->getTitle();
2486 $secureName = $title->getPrefixedDBkey();
2487 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2488 # Use an @ character to prevent collision with page names
2489 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2491 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2492 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2497 function endImageHistoryList()
2503 /* This function is called by all recent changes variants, by the page history,
2504 and by the user contributions list. It is responsible for formatting edit
2505 comments. It escapes any HTML in the comment, but adds some CSS to format
2506 auto-generated comments (from section editing) and formats [[wikilinks]].
2507 Main author: Erik Möller (moeller@scireview.de)
2509 function formatComment($comment)
2512 $comment = htmlspecialchars( $comment );
2514 # The pattern for autogen comments is / * foo * /, which makes for
2516 # We look for all comments, match any text before and after the comment,
2517 # add a separator where needed and format the comment itself with CSS
2518 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2523 if($pre) { $auto = $sep.' '.$auto; }
2524 if($post) { $auto .= ' '.$sep; }
2525 $auto='<span class="autocomment">'.$auto.'</span>';
2526 $comment=$pre.$auto.$post;
2529 # format regular and media links - all other wiki formatting
2531 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2532 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2533 # Handle link renaming [[foo|text]] will show link as "text"
2534 if( "" != $match[3] ) {
2539 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2540 # Media link; trail not supported.
2541 $linkRegexp = '/\[\[(.*?)\]\]/';
2542 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2544 # Other kind of link
2545 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2546 $trail = $submatch[1];
2550 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2551 if ($match[1][0] == ':')
2552 $match[1] = substr($match[1], 1);
2553 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2555 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2560 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2562 global $wgUser, $wgLang, $wgTitle;
2564 $datetime = $wgLang->timeanddate( $timestamp, true );
2565 $del = wfMsg( 'deleteimg' );
2566 $delall = wfMsg( 'deleteimgcompletely' );
2567 $cur = wfMsg( 'cur' );
2570 $url = Image
::wfImageUrl( $img );
2572 if ( $wgUser->isSysop() ) {
2573 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2575 $style = $this->getInternalLinkAttributes( $link, $delall );
2577 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2582 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2583 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2584 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2585 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2586 urlencode( $img ) );
2587 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2588 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2590 # Having live active links for non-logged in users
2591 # means that bots and spiders crawling our site can
2592 # inadvertently change content. Baaaad idea.
2593 $rlink = wfMsg( 'revertimg' );
2598 $userlink = $usertext;
2600 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2601 ':'.$usertext, $usertext );
2603 $nbytes = wfMsg( 'nbytes', $size );
2604 $style = $this->getInternalLinkAttributes( $url, $datetime );
2606 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2607 . " . . {$userlink} ({$nbytes})";
2609 if ( '' != $description && '*' != $description ) {
2610 $sk=$wgUser->getSkin();
2611 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2617 function tocIndent($level) {
2618 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2621 function tocUnindent($level) {
2622 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2625 # parameter level defines if we are on an indentation level
2626 function tocLine( $anchor, $tocline, $level ) {
2627 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2631 return '<div class="tocline">'.$link."</div>\n";
2636 function tocTable($toc) {
2637 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2638 # try min-width & co when somebody gets a chance
2639 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2641 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2642 '<b>'.wfMsg('toc').'</b>' .
2644 '</td></tr><tr id="tocinside"><td>'."\n".
2645 $toc."</td></tr></table>\n";
2648 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2649 function editSectionScript( $section, $head ) {
2650 global $wgTitle, $wgRequest;
2651 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2654 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2655 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2658 function editSectionLink( $section ) {
2660 global $wgTitle, $wgUser, $wgLang;
2662 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2663 # Section edit links would be out of sync on an old page.
2664 # But, if we're diffing to the current page, they'll be
2669 $editurl = '§ion='.$section;
2670 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2672 if( $wgLang->isRTL() ) {
2674 $nearside = 'right';
2679 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2683 // This function is called by EditPage.php and shows a bulletin board style
2684 // toolbar for common editing functions. It can be disabled in the user preferences.
2685 // The necsesary JavaScript code can be found in style/wikibits.js.
2686 function getEditToolbar() {
2687 global $wgStylePath, $wgLang, $wgMimeType;
2689 // toolarray an array of arrays which each include the filename of
2690 // the button image (without path), the opening tag, the closing tag,
2691 // and optionally a sample text that is inserted between the two when no
2692 // selection is highlighted.
2693 // The tip text is shown when the user moves the mouse over the button.
2695 // Already here are accesskeys (key), which are not used yet until someone
2696 // can figure out a way to make them work in IE. However, we should make
2697 // sure these keys are not defined on the edit page.
2699 array( 'image'=>'button_bold.png',
2702 'sample'=>wfMsg('bold_sample'),
2703 'tip'=>wfMsg('bold_tip'),
2706 array( "image"=>"button_italic.png",
2709 "sample"=>wfMsg("italic_sample"),
2710 "tip"=>wfMsg("italic_tip"),
2713 array( "image"=>"button_link.png",
2716 "sample"=>wfMsg("link_sample"),
2717 "tip"=>wfMsg("link_tip"),
2720 array( "image"=>"button_extlink.png",
2723 "sample"=>wfMsg("extlink_sample"),
2724 "tip"=>wfMsg("extlink_tip"),
2727 array( "image"=>"button_headline.png",
2730 "sample"=>wfMsg("headline_sample"),
2731 "tip"=>wfMsg("headline_tip"),
2734 array( "image"=>"button_image.png",
2735 "open"=>"[[".$wgLang->getNsText(NS_IMAGE
).":",
2737 "sample"=>wfMsg("image_sample"),
2738 "tip"=>wfMsg("image_tip"),
2741 array( "image"=>"button_media.png",
2742 "open"=>"[[".$wgLang->getNsText(NS_MEDIA
).":",
2744 "sample"=>wfMsg("media_sample"),
2745 "tip"=>wfMsg("media_tip"),
2748 array( "image"=>"button_math.png",
2749 "open"=>"\\<math\\>",
2750 "close"=>"\\</math\\>",
2751 "sample"=>wfMsg("math_sample"),
2752 "tip"=>wfMsg("math_tip"),
2755 array( "image"=>"button_nowiki.png",
2756 "open"=>"\\<nowiki\\>",
2757 "close"=>"\\</nowiki\\>",
2758 "sample"=>wfMsg("nowiki_sample"),
2759 "tip"=>wfMsg("nowiki_tip"),
2762 array( "image"=>"button_sig.png",
2766 "tip"=>wfMsg("sig_tip"),
2769 array( "image"=>"button_hr.png",
2770 "open"=>"\\n----\\n",
2773 "tip"=>wfMsg("hr_tip"),
2777 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2779 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2780 foreach($toolarray as $tool) {
2782 $image=$wgStylePath.'/images/'.$tool['image'];
2783 $open=$tool['open'];
2784 $close=$tool['close'];
2785 $sample = addslashes( $tool['sample'] );
2787 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2788 // Older browsers show a "speedtip" type message only for ALT.
2789 // Ideally these should be different, realistically they
2790 // probably don't need to be.
2791 $tip = addslashes( $tool['tip'] );
2793 #$key = $tool["key"];
2795 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2798 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2799 $toolbar.="document.writeln(\"</div>\");\n";
2801 $toolbar.="/*]]>*/\n</script>";
2805 /* public */ function suppressUrlExpansion() {