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