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 , $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
52 $this->linktrail
= wfMsg('linktrail');
55 function getSkinNames()
57 global $wgValidSkinNames;
58 return $wgValidSkinNames;
61 function getStylesheet()
63 return 'wikistandard.css';
65 function getSkinName() {
71 global $wgOut, $wgUser;
73 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
74 $q = $wgUser->getOption( 'quickbar' );
75 if ( '' == $q ) { $q = 0; }
79 function initPage( &$out )
81 $fname = 'Skin::initPage';
82 wfProfileIn( $fname );
84 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
86 $this->addMetadataLinks($out);
88 wfProfileOut( $fname );
91 function addMetadataLinks( &$out ) {
92 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
93 global $wgRightsPage, $wgRightsUrl;
95 if( $out->isArticleRelated() ) {
96 # note: buggy CC software only reads first "meta" link
97 if( $wgEnableCreativeCommonsRdf ) {
98 $out->addMetadataLink( array(
99 'title' => 'Creative Commons',
100 'type' => 'application/rdf+xml',
101 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
103 if( $wgEnableDublinCoreRdf ) {
104 $out->addMetadataLink( array(
105 'title' => 'Dublin Core',
106 'type' => 'application/rdf+xml',
107 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
111 if( $wgRightsPage ) {
112 $copy = Title
::newFromText( $wgRightsPage );
114 $copyright = $copy->getLocalURL();
117 if( !$copyright && $wgRightsUrl ) {
118 $copyright = $wgRightsUrl;
121 $out->addLink( array(
122 'rel' => 'copyright',
123 'href' => $copyright ) );
127 function outputPage( &$out ) {
128 global $wgDebugComments;
130 wfProfileIn( 'Skin::outputPage' );
131 $this->initPage( $out );
132 $out->out( $out->headElement() );
134 $out->out( "\n<body" );
135 $ops = $this->getBodyOptions();
136 foreach ( $ops as $name => $val ) {
137 $out->out( " $name='$val'" );
140 if ( $wgDebugComments ) {
141 $out->out( "<!-- Wiki debugging output:\n" .
142 $out->mDebugtext
. "-->\n" );
144 $out->out( $this->beforeContent() );
146 $out->out( $out->mBodytext
. "\n" );
148 $out->out( $this->afterContent() );
151 $out->out( $out->reportTime() );
153 $out->out( "\n</body></html>" );
156 function getHeadScripts() {
157 global $wgStylePath, $wgUser, $wgLang;
158 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
159 if( $wgUser->getID() != 0 ) { # logged in
160 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
161 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
162 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
167 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
168 function getUserStylesheet() {
169 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle;
170 $sheet = $this->getStylesheet();
171 $action = $wgRequest->getText('action');
172 $s = "@import \"$wgStylePath/$sheet\";\n";
173 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
174 if( $wgUser->getID() != 0 ) { # logged in
175 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
176 $s .= $wgRequest->getText('wpTextbox1');
178 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
179 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
182 $s .= $this->doGetUserStyles();
185 # placeholder, returns generated js in monobook
186 function getUserJs() {
190 function getUserStyles()
192 global $wgOut, $wgStylePath, $wgLang;
193 $s = "<style type='text/css'>\n";
194 $s .= "/*/*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
195 $s .= $this->getUserStylesheet();
201 function doGetUserStyles()
206 if ( 1 == $wgUser->getOption( 'underline' ) ) {
207 # Don't override browser settings
212 "text-decoration: none; }\n";
214 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
215 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
217 if ( 1 == $wgUser->getOption( 'justify' ) ) {
218 $s .= "#article { text-align: justify; }\n";
223 function getBodyOptions()
225 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
227 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
229 if ( 0 != $wgTitle->getNamespace() ) {
230 $a = array( 'bgcolor' => '#ffffec' );
232 else $a = array( 'bgcolor' => '#FFFFFF' );
233 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
234 (!$wgTitle->isProtected() ||
$wgUser->isSysop()) ) {
235 $t = wfMsg( 'editthispage' );
237 if ( !empty($redirect) ) {
238 $red = "&redirect={$redirect}";
240 if ( !empty($oldid) && ! isset( $diff ) ) {
241 $oid = "&oldid={$oldid}";
243 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
244 $s = 'document.location = "' .$s .'";';
245 $a +
= array ('ondblclick' => $s);
248 $a['onload'] = $wgOut->getOnloadHandler();
252 function getExternalLinkAttributes( $link, $text, $class='' )
254 global $wgUser, $wgOut, $wgLang;
256 $link = urldecode( $link );
257 $link = $wgLang->checkTitleEncoding( $link );
258 $link = str_replace( '_', ' ', $link );
259 $link = wfEscapeHTML( $link );
261 $r = ($class != '') ?
" class='$class'" : " class='external'";
263 if ( 1 == $wgUser->getOption( 'hover' ) ) {
264 $r .= " title=\"{$link}\"";
269 function getInternalLinkAttributes( $link, $text, $broken = false )
271 global $wgUser, $wgOut;
273 $link = urldecode( $link );
274 $link = str_replace( '_', ' ', $link );
275 $link = wfEscapeHTML( $link );
277 if ( $broken == 'stub' ) {
278 $r = ' class="stub"';
279 } else if ( $broken == 'yes' ) {
285 if ( 1 == $wgUser->getOption( 'hover' ) ) {
286 $r .= " title=\"{$link}\"";
291 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
293 global $wgUser, $wgOut;
295 if ( $broken == 'stub' ) {
296 $r = ' class="stub"';
297 } else if ( $broken == 'yes' ) {
303 if ( 1 == $wgUser->getOption( 'hover' ) ) {
304 $r .= ' title ="' . $nt->getEscapedText() . '"';
315 # This will be called immediately after the <body> tag. Split into
316 # two functions to make it easier to subclass.
318 function beforeContent()
320 global $wgUser, $wgOut, $wgSiteNotice;
322 if( $wgSiteNotice ) {
323 $note = "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
327 return $this->doBeforeContent() . $note;
330 function doBeforeContent()
332 global $wgUser, $wgOut, $wgTitle, $wgLang;
333 $fname = 'Skin::doBeforeContent';
334 wfProfileIn( $fname );
337 $qb = $this->qbSetting();
339 if( $langlinks = $this->otherLanguages() ) {
345 $borderhack = 'class="top"';
348 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
349 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
352 $left = ($qb == 1 ||
$qb == 3);
353 if($wgLang->isRTL()) $left = !$left;
356 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
357 $this->logoText() . '</td>';
359 $s .= $this->getQuickbarCompensator( $rows );
361 $l = $wgLang->isRTL() ?
'right' : 'left';
362 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
364 $s .= $this->topLinks() ;
365 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
367 $r = $wgLang->isRTL() ?
"left" : "right";
368 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
369 $s .= $this->nameAndLogin();
370 $s .= "\n<br />" . $this->searchForm() . "</td>";
373 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
376 if ( $shove && !$left ) { # Right
377 $s .= $this->getQuickbarCompensator( $rows );
379 $s .= "</tr>\n</table>\n</div>\n";
380 $s .= "\n<div id='article'>\n";
382 $s .= $this->pageTitle();
383 $s .= $this->pageSubtitle() ;
384 $s .= $this->getCategories();
385 wfProfileOut( $fname );
389 function getCategoryLinks () {
390 global $wgOut, $wgTitle, $wgUser, $wgParser;
391 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
393 if( !$wgUseCategoryMagic ) return '' ;
394 if( count( $wgOut->mCategoryLinks
) == 0 ) return '';
396 # Taken out so that they will be displayed in previews -- TS
397 #if( !$wgOut->isArticle() ) return '';
399 $t = implode ( ' | ' , $wgOut->mCategoryLinks
) ;
400 $s = $this->makeKnownLink( 'Special:Categories',
401 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
404 if($wgUseCategoryBrowser) {
407 $s.= $wgTitle->getAllParentCategories($catstack);
413 function getCategories() {
414 $catlinks=$this->getCategoryLinks();
415 if(!empty($catlinks)) {
416 return "<p class='catlinks'>{$catlinks}</p>";
420 function getQuickbarCompensator( $rows = 1 )
422 return "<td width='152' rowspan='{$rows}'> </td>";
425 # This gets called immediately before the </body> tag.
427 function afterContent()
429 global $wgUser, $wgOut, $wgServer;
430 global $wgTitle, $wgLang;
432 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
433 return $printfooter . $this->doAfterContent();
436 function printFooter() {
438 $url = htmlspecialchars( $wgTitle->getFullURL() );
439 return "<p>" . wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" ) .
440 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
443 function doAfterContent()
445 global $wgUser, $wgOut, $wgLang;
446 $fname = 'Skin::doAfterContent';
447 wfProfileIn( $fname );
448 wfProfileIn( $fname.'-1' );
450 $s = "\n</div><br style=\"clear:both\" />\n";
451 $s .= "\n<div id='footer'>";
452 $s .= '<table border="0" cellspacing="0"><tr>';
454 wfProfileOut( $fname.'-1' );
455 wfProfileIn( $fname.'-2' );
457 $qb = $this->qbSetting();
459 $left = ($qb == 1 ||
$qb == 3);
460 if($wgLang->isRTL()) $left = !$left;
462 if ( $shove && $left ) { # Left
463 $s .= $this->getQuickbarCompensator();
465 wfProfileOut( $fname.'-2' );
466 wfProfileIn( $fname.'-3' );
467 $l = $wgLang->isRTL() ?
'right' : 'left';
468 $s .= "<td class='bottom' align='$l' valign='top'>";
470 $s .= $this->bottomLinks();
471 $s .= "\n<br />" . $this->mainPageLink()
472 . ' | ' . $this->aboutLink()
473 . ' | ' . $this->specialLink( 'recentchanges' )
474 . ' | ' . $this->searchForm()
475 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
478 if ( $shove && !$left ) { # Right
479 $s .= $this->getQuickbarCompensator();
481 $s .= "</tr></table>\n</div>\n</div>\n";
483 wfProfileOut( $fname.'-3' );
484 wfProfileIn( $fname.'-4' );
485 if ( 0 != $qb ) { $s .= $this->quickBar(); }
486 wfProfileOut( $fname.'-4' );
487 wfProfileOut( $fname );
491 function pageTitleLinks()
493 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
495 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
496 $action = $wgRequest->getText( 'action' );
498 $s = $this->printableLink();
499 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
501 if ( $wgOut->isArticleRelated() ) {
502 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
503 $name = $wgTitle->getDBkey();
504 $link = wfEscapeHTML( Image
::wfImageUrl( $name ) );
505 $style = $this->getInternalLinkAttributes( $link, $name );
506 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
508 # This will show the "Approve" link if $wgUseApproval=true;
509 if ( isset ( $wgUseApproval ) && $wgUseApproval )
511 $t = $wgTitle->getDBkey();
512 $name = 'Approve this article' ;
513 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
514 #wfEscapeHTML( wfImageUrl( $name ) );
515 $style = $this->getExternalLinkAttributes( $link, $name );
516 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
519 if ( 'history' == $action ||
isset( $diff ) ||
isset( $oldid ) ) {
520 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
521 wfMsg( 'currentrev' ) );
524 if ( $wgUser->getNewtalk() ) {
525 # do not show "You have new messages" text when we are viewing our
528 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
529 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
530 $n =$wgUser->getName();
531 $tl = $this->makeKnownLink( $wgLang->getNsText(
532 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
533 wfMsg('newmessageslink') );
534 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
538 $undelete = $this->getUndeleteLink();
539 if( !empty( $undelete ) ) {
540 $s .= ' | '.$undelete;
545 function getUndeleteLink() {
546 global $wgUser, $wgTitle, $wgLang, $action;
547 if( $wgUser->isSysop() &&
548 (($wgTitle->getArticleId() == 0) ||
($action == "history")) &&
549 ($n = $wgTitle->isDeleted() ) ) {
550 return wfMsg( 'thisisdeleted',
551 $this->makeKnownLink(
552 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
553 wfMsg( 'restorelink', $n ) ) );
558 function printableLink()
560 global $wgOut, $wgFeedClasses, $wgRequest;
562 $baseurl = $_SERVER['REQUEST_URI'];
563 if( strpos( '?', $baseurl ) == false ) {
568 $baseurl = htmlspecialchars( $baseurl );
569 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
571 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
572 if( $wgOut->isSyndicated() ) {
573 foreach( $wgFeedClasses as $format => $class ) {
574 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
575 $s .= " | <a href=\"$feedurl\">{$format}</a>";
583 global $wgOut, $wgTitle, $wgUser;
585 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
586 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
590 function pageSubtitle()
594 $sub = $wgOut->getSubtitle();
596 global $wgExtraSubtitle;
597 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
599 $subpages = $this->subPageSubtitle();
600 $sub .= !empty($subpages)?
"</p><p class='subpages'>$subpages":'';
601 $s = "<p class='subtitle'>{$sub}</p>\n";
605 function subPageSubtitle()
607 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
609 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
610 $ptext=$wgTitle->getPrefixedText();
611 if(preg_match('/\//',$ptext)) {
612 $links = explode('/',$ptext);
615 foreach($links as $link) {
617 if ($c<count($links)) {
618 $growinglink .= $link;
619 $getlink = $this->makeLink( $growinglink, $link );
620 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
624 $subpages .= '< ';
626 $subpages .= $getlink;
635 function nameAndLogin()
637 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
639 $li = $wgLang->specialPage( 'Userlogin' );
640 $lo = $wgLang->specialPage( 'Userlogout' );
643 if ( 0 == $wgUser->getID() ) {
644 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
647 $tl = $this->makeKnownLink( $wgLang->getNsText(
648 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
649 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
651 $s .= $n . ' ('.$tl.')';
653 $s .= wfMsg('notloggedin');
656 $rt = $wgTitle->getPrefixedURL();
657 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
659 } else { $q = "returnto={$rt}"; }
661 $s .= "\n<br />" . $this->makeKnownLink( $li,
662 wfMsg( 'login' ), $q );
664 $n = $wgUser->getName();
665 $rt = $wgTitle->getPrefixedURL();
666 $tl = $this->makeKnownLink( $wgLang->getNsText(
667 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
668 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
672 $s .= $this->makeKnownLink( $wgLang->getNsText(
673 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
674 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
675 "returnto={$rt}" ) . ' | ' .
676 $this->specialLink( 'preferences' );
678 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
684 function getSearchLink() {
685 $searchPage =& Title
::makeTitle( NS_SPECIAL
, 'Search' );
686 return $searchPage->getLocalURL();
689 function escapeSearchLink() {
690 return htmlspecialchars( $this->getSearchLink() );
693 function searchForm()
696 $search = $wgRequest->getText( 'search' );
698 $s = '<form name="search" class="inline" method="post" action="'
699 . $this->escapeSearchLink() . "\">\n"
700 . '<input type="text" name="search" size="19" value="'
701 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
702 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" /> '
703 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
713 $s = $this->mainPageLink() . $sep
714 . $this->specialLink( 'recentchanges' );
716 if ( $wgOut->isArticleRelated() ) {
717 $s .= $sep . $this->editThisPage()
718 . $sep . $this->historyLink();
720 # Many people don't like this dropdown box
721 #$s .= $sep . $this->specialPagesList();
726 function bottomLinks()
728 global $wgOut, $wgUser, $wgTitle;
732 if ( $wgOut->isArticleRelated() ) {
733 $s .= '<strong>' . $this->editThisPage() . '</strong>';
734 if ( 0 != $wgUser->getID() ) {
735 $s .= $sep . $this->watchThisPage();
737 $s .= $sep . $this->talkLink()
738 . $sep . $this->historyLink()
739 . $sep . $this->whatLinksHere()
740 . $sep . $this->watchPageLinksLink();
742 if ( $wgTitle->getNamespace() == Namespace::getUser()
743 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
746 $id=User
::idFromName($wgTitle->getText());
747 $ip=User
::isIP($wgTitle->getText());
749 if($id ||
$ip) { # both anons and non-anons have contri list
750 $s .= $sep . $this->userContribsLink();
752 if ( 0 != $wgUser->getID() ) { # show only to signed in users
753 if($id) { # can only email non-anons
754 $s .= $sep . $this->emailUserLink();
758 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
759 $s .= "\n<br />" . $this->deleteThisPage() .
760 $sep . $this->protectThisPage() .
761 $sep . $this->moveThisPage();
763 $s .= "<br />\n" . $this->otherLanguages();
770 global $wgOut, $wgLang, $wgArticle, $wgRequest;
771 global $wgDisableCounters;
773 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
774 if ( ! $wgOut->isArticle() ) { return ''; }
775 if ( isset( $oldid ) ||
isset( $diff ) ) { return ''; }
776 if ( 0 == $wgArticle->getID() ) { return ''; }
779 if ( !$wgDisableCounters ) {
780 $count = $wgLang->formatNum( $wgArticle->getCount() );
782 $s = wfMsg( 'viewcount', $count );
786 $s .= ' ' . $this->getCredits();
788 return $s . ' ' . $this->getCopyright();
791 function getCredits() {
792 global $wgMaxCredits;
796 if (!isset($wgMaxCredits) ||
$wgMaxCredits == 0) {
797 $s = $this->lastModified();
799 $s = $this->getAuthorCredits();
800 if ($wgMaxCredits > 1) {
801 $s .= ' ' . $this->getContributorCredits();
808 function getAuthorCredits() {
809 global $wgLang, $wgArticle;
811 $last_author = $wgArticle->getUser();
813 if ($last_author == 0) {
814 $author_credit = wfMsg('anonymous');
816 $real_name = User
::whoIsReal($last_author);
817 if (!empty($real_name)) {
818 $author_credit = $real_name;
820 $author_credit = wfMsg('siteuser', User
::whoIs($last_author));
824 $timestamp = $wgArticle->getTimestamp();
826 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
830 return wfMsg('lastmodifiedby', $d, $author_credit);
833 function getContributorCredits() {
835 global $wgArticle, $wgMaxCredits, $wgLang;
837 # don't count last editor
839 $contributors = $wgArticle->getContributors($wgMaxCredits - 1);
841 $real_names = array();
842 $user_names = array();
844 # Sift for real versus user names
846 foreach ($contributors as $user_id => $user_parts) {
848 if (!empty($user_parts[1])) {
849 $real_names[$user_id] = $user_parts[1];
851 $user_names[$user_id] = $user_parts[0];
856 $real = $wgLang->listToText(array_values($real_names));
857 $user = $wgLang->listToText(array_values($user_names));
860 $user = wfMsg('siteusers', $user);
863 if ($contributors[0] && $contributors[0][0] > 0) {
864 $anon = wfMsg('anonymous');
869 $creds = $wgLang->listToText(array($real, $user, $anon));
871 return wfMsg('othercontribs', $creds);
874 function getCopyright() {
875 global $wgRightsPage, $wgRightsUrl, $wgRightsText;
877 if( $wgRightsPage ) {
878 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
879 } elseif( $wgRightsUrl ) {
880 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
885 $out .= wfMsg( 'copyright', $link );
889 function getCopyrightIcon() {
890 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
892 if( $wgRightsIcon ) {
893 $icon = htmlspecialchars( $wgRightsIcon );
895 $url = htmlspecialchars( $wgRightsUrl );
896 $out .= '<a href="'.$url.'">';
898 $text = htmlspecialchars( $wgRightsText );
899 $out .= "<img src=\"$icon\" alt='$text' />";
907 function getPoweredBy() {
909 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
910 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
914 function lastModified()
916 global $wgLang, $wgArticle;
918 $timestamp = $wgArticle->getTimestamp();
920 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
921 $s = ' ' . wfMsg( 'lastmodified', $d );
928 function logoText( $align = '' )
930 if ( '' != $align ) { $a = ' align="'.$align.'"'; }
933 $mp = wfMsg( 'mainpage' );
934 $titleObj = Title
::newFromText( $mp );
935 $s = '<a href="' . $titleObj->escapeLocalURL()
936 . '"><img'.$a.' src="'
937 . $this->getLogo() . '" alt="' . "[{$mp}]\" /></a>";
943 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
944 global $wgDisableUploads, $wgRemoteUploads;
946 $fname = 'Skin::quickBar';
947 wfProfileIn( $fname );
949 $action = $wgRequest->getText( 'action' );
950 $wpPreview = $wgRequest->getBool( 'wpPreview' );
951 $tns=$wgTitle->getNamespace();
953 $s = "\n<div id='quickbar'>";
954 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
957 $s .= $this->mainPageLink()
958 . $sep . $this->specialLink( 'recentchanges' )
959 . $sep . $this->specialLink( 'randompage' );
960 if ($wgUser->getID()) {
961 $s.= $sep . $this->specialLink( 'watchlist' ) ;
962 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
963 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
966 // only show watchlist link if logged in
967 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
968 $s .= "\n<br /><hr class='sep' />";
969 $articleExists = $wgTitle->getArticleId();
970 if ( $wgOut->isArticle() ||
$action =='edit' ||
$action =='history' ||
$wpPreview) {
971 if($wgOut->isArticle()) {
972 $s .= '<strong>' . $this->editThisPage() . '</strong>';
973 } else { # backlink to the article in edit or history mode
974 if($articleExists){ # no backlink if no article
977 $text = wfMsg('articlepage');
980 $text = wfMsg('viewtalkpage');
983 $text = wfMsg('userpage');
986 $text = wfMsg('viewtalkpage');
989 $text = wfMsg('wikipediapage');
992 $text = wfMsg('viewtalkpage');
995 $text = wfMsg('imagepage');
998 $text = wfMsg('viewtalkpage');
1001 $text= wfMsg('articlepage');
1004 $link = $wgTitle->getText();
1005 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
1006 $link = $nstext . ':' . $link ;
1009 $s .= $this->makeLink( $link, $text );
1010 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
1011 # we just throw in a "New page" text to tell the user that he's in edit mode,
1012 # and to avoid messing with the separator that is prepended to the next item
1013 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
1019 if( $tns%2
&& $action!='edit' && !$wpPreview) {
1020 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit§ion=new');
1024 watching could cause problems in edit mode:
1025 if user edits article, then loads "watch this article" in background and then saves
1026 article with "Watch this article" checkbox disabled, the article is transparently
1027 unwatched. Therefore we do not show the "Watch this page" link in edit mode
1029 if ( 0 != $wgUser->getID() && $articleExists) {
1030 if($action!='edit' && $action != 'submit' )
1032 $s .= $sep . $this->watchThisPage();
1034 if ( $wgTitle->userCanEdit() )
1035 $s .= $sep . $this->moveThisPage();
1037 if ( $wgUser->isSysop() and $articleExists ) {
1038 $s .= $sep . $this->deleteThisPage() .
1039 $sep . $this->protectThisPage();
1041 $s .= $sep . $this->talkLink();
1042 if ($articleExists && $action !='history') {
1043 $s .= $sep . $this->historyLink();
1045 $s.=$sep . $this->whatLinksHere();
1047 if($wgOut->isArticleRelated()) {
1048 $s .= $sep . $this->watchPageLinksLink();
1051 if ( Namespace::getUser() == $wgTitle->getNamespace()
1052 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1055 $id=User
::idFromName($wgTitle->getText());
1056 $ip=User
::isIP($wgTitle->getText());
1059 $s .= $sep . $this->userContribsLink();
1061 if ( 0 != $wgUser->getID() ) {
1062 if($id) { # can only email real users
1063 $s .= $sep . $this->emailUserLink();
1067 $s .= "\n<br /><hr class='sep' />";
1070 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads ||
$wgRemoteUploads ) ) {
1071 $s .= $this->specialLink( 'upload' ) . $sep;
1073 $s .= $this->specialLink( 'specialpages' )
1074 . $sep . $this->bugReportsLink();
1076 global $wgSiteSupportPage;
1077 if( $wgSiteSupportPage ) {
1078 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1079 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1082 $s .= "\n<br /></div>\n";
1083 wfProfileOut( $fname );
1087 function specialPagesList()
1089 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1090 require_once('SpecialPage.php');
1092 $pages = SpecialPage
::getPages();
1094 foreach ( $pages[''] as $name => $page ) {
1095 $a[$name] = $page->getDescription();
1097 if ( $wgUser->isSysop() )
1099 foreach ( $pages['sysop'] as $name => $page ) {
1100 $a[$name] = $page->getDescription();
1103 if ( $wgUser->isDeveloper() )
1105 foreach ( $pages['developer'] as $name => $page ) {
1106 $a[$name] = $page->getDescription() ;
1109 $go = wfMsg( 'go' );
1110 $sp = wfMsg( 'specialpages' );
1111 $spp = $wgLang->specialPage( 'Specialpages' );
1113 $s = '<form id="specialpages" method="get" class="inline" ' .
1114 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1115 $s .= "<select name=\"wpDropdown\">\n";
1116 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1118 foreach ( $a as $name => $desc ) {
1119 $p = $wgLang->specialPage( $name );
1120 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1122 $s .= "</select>\n";
1123 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1128 function mainPageLink()
1130 $mp = wfMsg( 'mainpage' );
1131 $s = $this->makeKnownLink( $mp, $mp );
1135 function copyrightLink()
1137 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1138 wfMsg( 'copyrightpagename' ) );
1142 function aboutLink()
1144 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1145 wfMsg( 'aboutwikipedia' ) );
1150 function disclaimerLink()
1152 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1153 wfMsg( 'disclaimers' ) );
1157 function editThisPage()
1159 global $wgOut, $wgTitle, $wgRequest;
1161 $oldid = $wgRequest->getVal( 'oldid' );
1162 $diff = $wgRequest->getVal( 'diff' );
1163 $redirect = $wgRequest->getVal( 'redirect' );
1165 if ( ! $wgOut->isArticleRelated() ) {
1166 $s = wfMsg( 'protectedpage' );
1168 $n = $wgTitle->getPrefixedText();
1169 if ( $wgTitle->userCanEdit() ) {
1170 $t = wfMsg( 'editthispage' );
1172 #$t = wfMsg( "protectedpage" );
1173 $t = wfMsg( 'viewsource' );
1177 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1178 if ( $oldid && ! isset( $diff ) ) {
1179 $oid = "&oldid={$oldid}";
1181 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1186 function deleteThisPage()
1188 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1190 $diff = $wgRequest->getVal( 'diff' );
1191 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1192 $n = $wgTitle->getPrefixedText();
1193 $t = wfMsg( 'deletethispage' );
1195 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1202 function protectThisPage()
1204 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1206 $diff = $wgRequest->getVal( 'diff' );
1207 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1208 $n = $wgTitle->getPrefixedText();
1210 if ( $wgTitle->isProtected() ) {
1211 $t = wfMsg( 'unprotectthispage' );
1212 $q = 'action=unprotect';
1214 $t = wfMsg( 'protectthispage' );
1215 $q = 'action=protect';
1217 $s = $this->makeKnownLink( $n, $t, $q );
1224 function watchThisPage()
1226 global $wgUser, $wgOut, $wgTitle;
1228 if ( $wgOut->isArticleRelated() ) {
1229 $n = $wgTitle->getPrefixedText();
1231 if ( $wgTitle->userIsWatching() ) {
1232 $t = wfMsg( 'unwatchthispage' );
1233 $q = 'action=unwatch';
1235 $t = wfMsg( 'watchthispage' );
1236 $q = 'action=watch';
1238 $s = $this->makeKnownLink( $n, $t, $q );
1240 $s = wfMsg( 'notanarticle' );
1245 function moveThisPage()
1247 global $wgTitle, $wgLang;
1249 if ( $wgTitle->userCanEdit() ) {
1250 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1251 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1252 } // no message if page is protected - would be redundant
1256 function historyLink()
1260 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1261 wfMsg( 'history' ), 'action=history' );
1265 function whatLinksHere()
1267 global $wgTitle, $wgLang;
1269 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1270 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1274 function userContribsLink()
1276 global $wgTitle, $wgLang;
1278 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1279 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1283 function emailUserLink()
1285 global $wgTitle, $wgLang;
1287 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1288 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1292 function watchPageLinksLink()
1294 global $wgOut, $wgTitle, $wgLang;
1296 if ( ! $wgOut->isArticleRelated() ) {
1297 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1299 $s = $this->makeKnownLink( $wgLang->specialPage(
1300 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1301 'target=' . $wgTitle->getPrefixedURL() );
1306 function otherLanguages()
1308 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1310 $a = $wgOut->getLanguageLinks();
1311 if ( 0 == count( $a ) ) {
1312 if ( !$wgUseNewInterlanguage ) return '';
1313 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1314 if ( $ns != 0 AND $ns != 1 ) return '' ;
1316 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1317 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1318 wfMsg( 'intl' ) , $x );
1321 if ( !$wgUseNewInterlanguage ) {
1322 $s = wfMsg( 'otherlanguages' ) . ': ';
1324 global $wgLanguageCode ;
1325 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1326 $x .= '&xl='.$wgLanguageCode ;
1327 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1328 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1331 $s = wfMsg( 'otherlanguages' ) . ': ';
1333 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1334 foreach( $a as $l ) {
1335 if ( ! $first ) { $s .= ' | '; }
1338 $nt = Title
::newFromText( $l );
1339 $url = $nt->getFullURL();
1340 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1342 if ( '' == $text ) { $text = $l; }
1343 $style = $this->getExternalLinkAttributes( $l, $text );
1344 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1346 if($wgLang->isRTL()) $s .= '</span>';
1350 function bugReportsLink()
1352 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1353 wfMsg( 'bugreports' ) );
1359 global $wgLinkCache;
1360 $t1 = Title
::newFromText( gmdate( 'F j' ) );
1361 $t2 = Title
::newFromText( gmdate( 'Y' ) );
1363 $wgLinkCache->suspend();
1364 $id = $t1->getArticleID();
1365 $wgLinkCache->resume();
1368 $s = $this->makeBrokenLink( $t1->getText() );
1370 $s = $this->makeKnownLink( $t1->getText() );
1374 $wgLinkCache->suspend();
1375 $id = $t2->getArticleID();
1376 $wgLinkCache->resume();
1379 $s .= $this->makeBrokenLink( $t2->getText() );
1381 $s .= $this->makeKnownLink( $t2->getText() );
1388 global $wgLang, $wgTitle, $wgLinkCache;
1390 $tns = $wgTitle->getNamespace();
1391 if ( -1 == $tns ) { return ''; }
1393 $pn = $wgTitle->getText();
1394 $tp = wfMsg( 'talkpage' );
1395 if ( Namespace::isTalk( $tns ) ) {
1396 $lns = Namespace::getSubject( $tns );
1399 $text = wfMsg('articlepage');
1402 $text = wfMsg('userpage');
1405 $text = wfMsg('wikipediapage');
1408 $text = wfMsg('imagepage');
1411 $text= wfMsg('articlepage');
1415 $lns = Namespace::getTalk( $tns );
1418 $n = $wgLang->getNsText( $lns );
1419 if ( '' == $n ) { $link = $pn; }
1420 else { $link = $n.':'.$pn; }
1422 $wgLinkCache->suspend();
1423 $s = $this->makeLink( $link, $text );
1424 $wgLinkCache->resume();
1429 function commentLink()
1431 global $wgLang, $wgTitle, $wgLinkCache;
1433 $tns = $wgTitle->getNamespace();
1434 if ( -1 == $tns ) { return ''; }
1436 $lns = ( Namespace::isTalk( $tns ) ) ?
$tns : Namespace::getTalk( $tns );
1438 # assert Namespace::isTalk( $lns )
1440 $n = $wgLang->getNsText( $lns );
1441 $pn = $wgTitle->getText();
1445 $wgLinkCache->suspend();
1446 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit§ion=new');
1447 $wgLinkCache->resume();
1452 # After all the page content is transformed into HTML, it makes
1453 # a final pass through here for things like table backgrounds.
1455 function transformContent( $text )
1460 # Note: This function MUST call getArticleID() on the link,
1461 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1463 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1464 wfProfileIn( 'Skin::makeLink' );
1465 $nt = Title
::newFromText( $title );
1467 $result = $this->makeLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1469 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1470 $result = $text == "" ?
$title : $text;
1473 wfProfileOut( 'Skin::makeLink' );
1477 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1478 $nt = Title
::newFromText( $title );
1480 return $this->makeKnownLinkObj( Title
::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1482 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1483 return $text == '' ?
$title : $text;
1487 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1488 $nt = Title
::newFromText( $title );
1490 return $this->makeBrokenLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1492 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1493 return $text == '' ?
$title : $text;
1497 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1498 $nt = Title
::newFromText( $title );
1500 return $this->makeStubLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1502 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1503 return $text == '' ?
$title : $text;
1507 # Pass a title object, not a title string
1508 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1510 global $wgOut, $wgUser;
1511 if ( $nt->isExternal() ) {
1512 $u = $nt->getFullURL();
1513 $link = $nt->getPrefixedURL();
1514 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1515 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1518 if ( '' != $trail ) {
1519 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1524 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1525 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1526 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1527 } elseif ( ( -1 == $nt->getNamespace() ) ||
1528 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1529 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1531 $aid = $nt->getArticleID() ;
1533 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1535 $threshold = $wgUser->getOption('stubthreshold') ;
1536 if ( $threshold > 0 ) {
1537 $res = wfQuery ( "SELECT LENGTH(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ
) ;
1539 if ( wfNumRows( $res ) > 0 ) {
1540 $s = wfFetchObject( $res );
1542 if ( $s->cur_is_redirect
OR $s->cur_namespace
!= 0 ) {
1543 $size = $threshold*2 ; # Really big
1545 wfFreeResult( $res );
1547 $size = $threshold*2 ; # Really big
1552 if ( $size < $threshold ) {
1553 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1555 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1562 # Pass a title object, not a title string
1563 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1565 global $wgOut, $wgTitle, $wgInputEncoding;
1567 $fname = 'Skin::makeKnownLinkObj';
1568 wfProfileIn( $fname );
1570 $link = $nt->getPrefixedURL();
1572 if ( '' == $link ) {
1574 if ( '' == $text ) {
1575 $text = htmlspecialchars( $nt->getFragment() );
1578 $u = $nt->escapeLocalURL( $query );
1580 if ( '' != $nt->getFragment() ) {
1581 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1582 $replacearray = array(
1586 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1588 if ( '' == $text ) {
1589 $text = htmlspecialchars( $nt->getPrefixedText() );
1591 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1594 if ( '' != $trail ) {
1595 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1600 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1601 wfProfileOut( $fname );
1605 # Pass a title object, not a title string
1606 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1608 global $wgOut, $wgUser;
1610 $fname = 'Skin::makeBrokenLinkObj';
1611 wfProfileIn( $fname );
1613 if ( '' == $query ) {
1616 $q = 'action=edit&'.$query;
1618 $u = $nt->escapeLocalURL( $q );
1620 if ( '' == $text ) {
1621 $text = htmlspecialchars( $nt->getPrefixedText() );
1623 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1626 if ( '' != $trail ) {
1627 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1632 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1633 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1635 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1638 wfProfileOut( $fname );
1642 # Pass a title object, not a title string
1643 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1645 global $wgOut, $wgUser;
1647 $link = $nt->getPrefixedURL();
1649 $u = $nt->escapeLocalURL( $query );
1651 if ( '' == $text ) {
1652 $text = htmlspecialchars( $nt->getPrefixedText() );
1654 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1657 if ( '' != $trail ) {
1658 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1663 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1664 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1666 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1671 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1673 $u = $nt->escapeLocalURL( $query );
1674 if ( '' == $text ) {
1675 $text = htmlspecialchars( $nt->getPrefixedText() );
1678 if ( '' != $trail ) {
1679 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1684 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1687 /* these are used extensively in SkinPHPTal, but also some other places */
1688 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1689 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1690 $this->checkTitle($title, $name);
1691 return $title->getLocalURL( $urlaction );
1693 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1694 $title = Title
::newFromText( $name );
1695 $title = $title->getTalkPage();
1696 $this->checkTitle($title, $name);
1697 return $title->getLocalURL( $urlaction );
1699 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1700 $title = Title
::newFromText( $name );
1701 $title= $title->getSubjectPage();
1702 $this->checkTitle($title, $name);
1703 return $title->getLocalURL( $urlaction );
1705 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1706 $title = Title
::newFromText( wfMsg($name) );
1707 $this->checkTitle($title, $name);
1708 return $title->getLocalURL( $urlaction );
1710 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1711 $title = Title
::newFromText( $name );
1712 $this->checkTitle($title, $name);
1713 return $title->getLocalURL( $urlaction );
1715 # this can be passed the NS number as defined in Language.php
1716 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1717 $title = Title
::makeTitle( $namespace, $name );
1718 $this->checkTitle($title, $name);
1719 return $title->getLocalURL( $urlaction );
1722 /* these return an array with the 'href' and boolean 'exists' */
1723 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1724 $title = Title
::newFromText( $name );
1725 $this->checkTitle($title, $name);
1727 'href' => $title->getLocalURL( $urlaction ),
1728 'exists' => $title->getArticleID() != 0?
true:false
1731 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1732 $title = Title
::newFromText( $name );
1733 $title = $title->getTalkPage();
1734 $this->checkTitle($title, $name);
1736 'href' => $title->getLocalURL( $urlaction ),
1737 'exists' => $title->getArticleID() != 0?
true:false
1740 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1741 $title = Title
::newFromText( $name );
1742 $title= $title->getSubjectPage();
1743 $this->checkTitle($title, $name);
1745 'href' => $title->getLocalURL( $urlaction ),
1746 'exists' => $title->getArticleID() != 0?
true:false
1749 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1750 $title = Title
::newFromText( wfMsg($name) );
1751 $this->checkTitle($title, $name);
1753 'href' => $title->getLocalURL( $urlaction ),
1754 'exists' => $title->getArticleID() != 0?
true:false
1758 # make sure we have some title to operate on
1759 /*static*/ function checkTitle ( &$title, &$name ) {
1760 if(!is_object($title)) {
1761 $title = Title
::newFromText( $name );
1762 if(!is_object($title)) {
1763 $title = Title
::newFromText( '<error: link target missing>' );
1768 function fnamePart( $url )
1770 $basename = strrchr( $url, '/' );
1771 if ( false === $basename ) { $basename = $url; }
1772 else { $basename = substr( $basename, 1 ); }
1773 return wfEscapeHTML( $basename );
1776 function makeImage( $url, $alt = '' )
1780 if ( '' == $alt ) { $alt = $this->fnamePart( $url ); }
1781 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1785 function makeImageLink( $name, $url, $alt = '' ) {
1786 $nt = Title
::makeTitle( Namespace::getImage(), $name );
1787 return $this->makeImageLinkObj( $nt, $alt );
1790 function makeImageLinkObj( $nt, $alt = '' ) {
1791 global $wgLang, $wgUseImageResize;
1792 $img = Image
::newFromTitle( $nt );
1793 $url = $img->getURL();
1796 $prefix = $postfix = '';
1798 if ( $wgUseImageResize ) {
1799 # Check if the alt text is of the form "options|alt text"
1801 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1802 # * left no resizing, just left align. label is used for alt= only
1803 # * right same, but right aligned
1804 # * none same, but not aligned
1805 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1806 # * center center the image
1807 # * framed Keep original image size, no magnify-button.
1809 $part = explode( '|', $alt);
1811 $mwThumb =& MagicWord
::get( MAG_IMG_THUMBNAIL
);
1812 $mwLeft =& MagicWord
::get( MAG_IMG_LEFT
);
1813 $mwRight =& MagicWord
::get( MAG_IMG_RIGHT
);
1814 $mwNone =& MagicWord
::get( MAG_IMG_NONE
);
1815 $mwWidth =& MagicWord
::get( MAG_IMG_WIDTH
);
1816 $mwCenter =& MagicWord
::get( MAG_IMG_CENTER
);
1817 $mwFramed =& MagicWord
::get( MAG_IMG_FRAMED
);
1818 $alt = $part[count($part)-1];
1820 $height = $framed = $thumb = false;
1822 foreach( $part as $key => $val ) {
1823 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1825 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1826 # remember to set an alignment, don't render immediately
1828 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1829 # remember to set an alignment, don't render immediately
1831 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1832 # remember to set an alignment, don't render immediately
1834 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1835 # remember to set an alignment, don't render immediately
1837 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1838 # $match is the image width in pixels
1839 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1840 $width = intval( $m[1] );
1841 $height = intval( $m[2] );
1843 $width = intval($match);
1845 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1849 if ( 'center' == $align )
1851 $prefix = '<span style="text-align: center">';
1852 $postfix = '</span>';
1856 if ( $thumb ||
$framed ) {
1858 # Create a thumbnail. Alignment depends on language
1859 # writing direction, # right aligned for left-to-right-
1860 # languages ("Western languages"), left-aligned
1861 # for right-to-left-languages ("Semitic languages")
1863 # If thumbnail width has not been provided, it is set
1864 # here to 180 pixels
1865 if ( $align == '' ) {
1866 $align = $wgLang->isRTL() ?
'left' : 'right';
1868 if ( ! isset($width) ) {
1871 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed ).$postfix;
1873 } elseif ( isset($width) ) {
1875 # Create a resized image, without the additional thumbnail
1878 if ( ( ! $height === false )
1879 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1880 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1881 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1882 $width = $img->getWidth() * $height / $img->getHeight();
1884 $url = $img->createThumb( $width );
1886 } # endif $wgUseImageResize
1888 if ( empty( $alt ) ) {
1889 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1891 $alt = htmlspecialchars( $alt );
1893 $u = $nt->escapeLocalURL();
1896 $s = str_replace( "$1", $img->getName(), wfMsg('missingimage') );
1897 $s .= "<br>{$alt}<br>{$url}<br>\n";
1899 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1900 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1902 if ( '' != $align ) {
1903 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1905 return str_replace("\n", ' ',$prefix.$s.$postfix);
1909 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false ) {
1910 global $wgStylePath, $wgLang;
1911 # $image = Title::makeTitle( Namespace::getImage(), $name );
1912 $url = $img->getURL();
1914 #$label = htmlspecialchars( $label );
1915 $alt = preg_replace( '/<[^>]*>/', '', $label);
1916 $alt = htmlspecialchars( $alt );
1918 if ( $img->exists() )
1920 $width = $img->getWidth();
1921 $height = $img->getHeight();
1923 $width = $height = 200;
1927 // Use image dimensions, don't scale
1929 $oboxwidth = $boxwidth +
2;
1930 $boxheight = $height;
1933 $h = intval( $height/($width/$boxwidth) );
1934 $oboxwidth = $boxwidth +
2;
1935 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1937 $boxwidth *= $boxheight/$h;
1941 $thumbUrl = $img->createThumb( $boxwidth );
1944 $u = $img->getEscapeLocalURL();
1946 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1947 $magnifyalign = $wgLang->isRTL() ?
'left' : 'right';
1948 $textalign = $wgLang->isRTL() ?
' style="text-align:right"' : '';
1950 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1951 if ( $thumbUrl == '' ) {
1952 $s .= str_replace( "$1", $img->getName(), wfMsg('missingimage') );
1955 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1956 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1957 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1961 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1962 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1963 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1964 'width="15" height="11" alt="'.$more.'" /></a></div>';
1967 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1968 return str_replace("\n", ' ', $s);
1971 function makeMediaLink( $name, $url, $alt = "" ) {
1972 $nt = Title
::makeTitle( Namespace::getMedia(), $name );
1973 return $this->makeMediaLinkObj( $nt, $alt );
1976 function makeMediaLinkObj( $nt, $alt = "" )
1978 if ( ! isset( $nt ) )
1980 ### HOTFIX. Instead of breaking, return empry string.
1983 $name = $nt->getDBKey();
1984 $url = Image
::wfImageUrl( $name );
1985 if ( empty( $alt ) ) {
1986 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1989 $u = htmlspecialchars( $url );
1990 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1995 function specialLink( $name, $key = "" )
1999 if ( '' == $key ) { $key = strtolower( $name ); }
2000 $pn = $wgLang->ucfirst( $name );
2001 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2005 function makeExternalLink( $url, $text, $escape = true ) {
2006 $style = $this->getExternalLinkAttributes( $url, $text );
2007 $url = htmlspecialchars( $url );
2009 $text = htmlspecialchars( $text );
2011 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2014 # Called by history lists and recent changes
2017 # Returns text for the start of the tabular part of RC
2018 function beginRecentChangesList()
2020 $this->rc_cache
= array() ;
2021 $this->rcMoveIndex
= 0;
2022 $this->rcCacheIndex
= 0 ;
2023 $this->lastdate
= '';
2024 $this->rclistOpen
= false;
2028 function beginImageHistoryList()
2030 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2031 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2035 # Returns text for the end of RC
2036 # If enhanced RC is in use, returns pretty much all the text
2037 function endRecentChangesList()
2039 $s = $this->recentChangesBlock() ;
2040 if( $this->rclistOpen
) {
2046 # Enhanced RC ungrouped line
2047 function recentChangesBlockLine ( $rcObj )
2049 global $wgStylePath, $wgLang ;
2051 # Get rc_xxxx variables
2052 extract( $rcObj->mAttribs
) ;
2053 $curIdEq = 'curid='.$rc_cur_id;
2058 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2061 if ( $rc_type == RC_MOVE
) {
2062 $r .= ' ';
2064 # M & N (minor & new)
2065 $M = wfMsg( 'minoreditletter' );
2066 $N = wfMsg( 'newpageletter' );
2068 if ( $rc_type == RC_NEW
) {
2081 $r .= ' '.$rcObj->timestamp
.' ' ;
2085 $link = $rcObj->link
;
2086 if ( $rcObj->watched
) $link = '<strong>'.$link.'</strong>' ;
2091 $r .= $rcObj->curlink
;
2095 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2098 $r .= ') . . '.$rcObj->userlink
;
2099 $r .= $rcObj->usertalklink
;
2102 if ( $rc_comment != '' && $rc_type != RC_MOVE
) {
2103 $rc_comment=$this->formatComment($rc_comment);
2104 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2112 function recentChangesBlockGroup ( $block )
2114 global $wgStylePath, $wgLang ;
2117 $M = wfMsg( 'minoreditletter' );
2118 $N = wfMsg( 'newpageletter' );
2120 # Collate list of users
2122 $userlinks = array () ;
2123 foreach ( $block AS $rcObj ) {
2124 $oldid = $rcObj->mAttribs
['rc_last_oldid'];
2125 if ( $rcObj->mAttribs
['rc_new'] ) $isnew = true ;
2126 $u = $rcObj->userlink
;
2127 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2131 # Sort the list and convert to text
2132 krsort ( $userlinks ) ;
2133 asort ( $userlinks ) ;
2135 foreach ( $userlinks as $userlink => $count) {
2137 if ( $count > 1 ) $text .= " ({$count}×)" ;
2138 array_push ( $users , $text ) ;
2140 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2143 $rci = 'RCI'.$this->rcCacheIndex
;
2144 $rcl = 'RCL'.$this->rcCacheIndex
;
2145 $rcm = 'RCM'.$this->rcCacheIndex
;
2146 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2147 $arrowdir = $wgLang->isRTL() ?
'l' : 'r';
2148 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2149 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2155 if ( $isnew ) $r .= $N ;
2156 else $r .= ' ' ;
2157 $r .= ' ' ; # Minor
2160 $r .= ' '.$block[0]->timestamp
.' ' ;
2164 $link = $block[0]->link
;
2165 if ( $block[0]->watched
) $link = '<strong>'.$link.'</strong>' ;
2168 $curIdEq = 'curid=' . $block[0]->mAttribs
['rc_cur_id'];
2169 if ( $block[0]->mAttribs
['rc_type'] != RC_LOG
) {
2171 $r .= ' ('.count($block).' ' ;
2172 if ( $isnew ) $r .= wfMsg('changes');
2173 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2174 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2178 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2186 $r .= '<div id="'.$rci.'" style="display:none">' ;
2187 foreach ( $block AS $rcObj ) {
2188 # Get rc_xxxx variables
2189 extract( $rcObj->mAttribs
);
2191 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2192 $r .= '<tt> ' ;
2193 if ( $rc_new ) $r .= $N ;
2194 else $r .= ' ' ;
2195 if ( $rc_minor ) $r .= $M ;
2196 else $r .= ' ' ;
2200 if ( $rc_last_oldid != 0 ) {
2201 $o = 'oldid='.$rc_last_oldid ;
2203 if ( $rc_type == RC_LOG
) {
2204 $link = $rcObj->timestamp
;
2206 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp
, "{$curIdEq}&$o" ) ;
2208 $link = '<tt>'.$link.'</tt>' ;
2212 $r .= $rcObj->curlink
;
2214 $r .= $rcObj->lastlink
;
2215 $r .= ') . . '.$rcObj->userlink
;
2216 $r .= $rcObj->usertalklink
;
2217 if ( $rc_comment != '' ) {
2218 $rc_comment=$this->formatComment($rc_comment);
2219 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2225 $this->rcCacheIndex++
;
2229 # If enhanced RC is in use, this function takes the previously cached
2230 # RC lines, arranges them, and outputs the HTML
2231 function recentChangesBlock ()
2233 global $wgStylePath ;
2234 if ( count ( $this->rc_cache
) == 0 ) return '' ;
2236 foreach ( $this->rc_cache
AS $secureName => $block ) {
2237 if ( count ( $block ) < 2 ) {
2238 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2240 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2244 return '<div>'.$blockOut.'</div>' ;
2247 # Called in a loop over all displayed RC entries
2248 # Either returns the line, or caches it for later use
2249 function recentChangesLine( &$rc, $watched = false )
2252 $usenew = $wgUser->getOption( 'usenewrc' );
2254 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2256 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2260 function recentChangesLineOld( &$rc, $watched = false )
2262 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2264 # Extract DB fields into local scope
2265 extract( $rc->mAttribs
);
2266 $curIdEq = 'curid=' . $rc_cur_id;
2268 # Make date header if necessary
2269 $date = $wgLang->date( $rc_timestamp, true);
2271 if ( $date != $this->lastdate
) {
2272 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2273 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2274 $this->lastdate
= $date;
2275 $this->rclistOpen
= true;
2279 if ( $rc_type == RC_MOVE
) {
2281 $s .= '(' . wfMsg( 'diff' ) . ') (';
2283 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2286 # "[[x]] moved to [[y]]"
2288 $s .= wfMsg( '1movedto2', $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2289 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2293 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2294 $diffLink = wfMsg( 'diff' );
2296 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2297 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid ,'' ,'' , ' tabindex="'.$rc->counter
.'"');
2299 $s .= '('.$diffLink.') (';
2302 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2305 # M and N (minor and new)
2306 $M = wfMsg( 'minoreditletter' );
2307 $N = wfMsg( 'newpageletter' );
2308 if ( $rc_minor ) { $s .= ' <strong>'.$M.'</strong>'; }
2309 if ( $rc_type == RC_NEW
) { $s .= '<strong>'.$N.'</strong>'; }
2312 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2315 $articleLink = '<strong>'.$articleLink.'</strong>';
2317 $s .= ' '.$articleLink;
2322 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2324 # User link (or contributions for unregistered users)
2325 if ( 0 == $rc_user ) {
2326 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2327 $rc_user_text, 'target=' . $rc_user_text );
2329 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2334 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2335 global $wgDisableAnonTalk;
2336 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2339 $utns=$wgLang->getNsText(NS_USER_TALK
);
2340 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2344 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2345 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2346 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2350 if($userTalkLink) $userTalkLink .= ' | ';
2351 $userTalkLink .= $blockLink;
2353 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2356 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
) {
2357 $rc_comment=$this->formatComment($rc_comment);
2358 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2365 # function recentChangesLineNew( $ts, $u, $ut, $ns, $ttl, $c, $isminor, $isnew, $watched = false, $oldid = 0 , $diffid = 0 )
2366 function recentChangesLineNew( &$baseRC, $watched = false )
2368 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2370 # Create a specialised object
2371 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2373 # Extract fields from DB into the function scope (rc_xxxx variables)
2374 extract( $rc->mAttribs
);
2375 $curIdEq = 'curid=' . $rc_cur_id;
2377 # If it's a new day, add the headline and flush the cache
2378 $date = $wgLang->date( $rc_timestamp, true);
2380 if ( $date != $this->lastdate
) {
2381 # Process current cache
2382 $ret = $this->recentChangesBlock () ;
2383 $this->rc_cache
= array() ;
2384 $ret .= "<h4>{$date}</h4>\n";
2385 $this->lastdate
= $date;
2389 if ( $rc_type == RC_MOVE
) {
2390 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' );
2391 $clink .= ' ' . wfMsg('movedto') . ' ';
2392 $clink .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' );
2394 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2397 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2398 $rc->watched
= $watched ;
2399 $rc->link
= $clink ;
2400 $rc->timestamp
= $time;
2403 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE
) {
2404 $curLink = wfMsg( 'cur' );
2406 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ),
2407 $curIdEq.'&diff=0&oldid='.$rc_this_oldid ,'' ,'' , ' tabindex="'.$baseRC->counter
.'"' );
2411 $titleObj = $rc->getTitle();
2412 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE
) {
2413 $lastLink = wfMsg( 'last' );
2415 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2416 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2419 # Make user link (or user contributions for unregistered users)
2420 if ( 0 == $rc_user ) {
2421 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2422 $rc_user_text, 'target=' . $rc_user_text );
2424 $userLink = $this->makeLink( $wgLang->getNsText(
2425 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2428 $rc->userlink
= $userLink ;
2429 $rc->lastlink
= $lastLink ;
2430 $rc->curlink
= $curLink ;
2432 # Make user talk link
2433 $utns=$wgLang->getNsText(NS_USER_TALK
);
2434 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2435 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2437 global $wgDisableAnonTalk;
2438 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2439 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2440 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2441 if( $wgDisableAnonTalk )
2442 $rc->usertalklink
= ' ('.$blockLink.')';
2444 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2446 if( $wgDisableAnonTalk && ($rc_user == 0) )
2447 $rc->usertalklink
= '';
2449 $rc->usertalklink
= ' ('.$userTalkLink.')';
2452 # Put accumulated information into the cache, for later display
2453 # Page moves go on their own line
2454 $title = $rc->getTitle();
2455 $secureName = $title->getPrefixedDBkey();
2456 if ( $rc_type == RC_MOVE
) {
2457 # Use an @ character to prevent collision with page names
2458 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2460 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2461 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2466 function endImageHistoryList()
2472 /* This function is called by all recent changes variants, by the page history,
2473 and by the user contributions list. It is responsible for formatting edit
2474 comments. It escapes any HTML in the comment, but adds some CSS to format
2475 auto-generated comments (from section editing) and formats [[wikilinks]].
2476 Main author: Erik Möller (moeller@scireview.de)
2478 function formatComment($comment)
2481 $comment=wfEscapeHTML($comment);
2483 # The pattern for autogen comments is / * foo * /, which makes for
2485 # We look for all comments, match any text before and after the comment,
2486 # add a separator where needed and format the comment itself with CSS
2487 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2492 if($pre) { $auto = $sep.' '.$auto; }
2493 if($post) { $auto .= ' '.$sep; }
2494 $auto='<span class="autocomment">'.$auto.'</span>';
2495 $comment=$pre.$auto.$post;
2498 # format regular and media links - all other wiki formatting
2500 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\]/',$comment,$match)) {
2502 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2504 if(preg_match('/^'.$medians.'/i',$match[1])) {
2505 $func='makeMediaLink';
2507 # Handle link renaming [[foo|text]] will show link as "text"
2508 if(isset($match[3]) ) {
2510 preg_replace('/\[\[(.*?)\]\]/',
2511 $this->$func($match[1],$match[3]),$comment,1);
2514 preg_replace('/\[\[(.*?)\]\]/',
2515 $this->$func($match[1],$match[1]),$comment,1);
2523 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2525 global $wgUser, $wgLang, $wgTitle;
2527 $datetime = $wgLang->timeanddate( $timestamp, true );
2528 $del = wfMsg( 'deleteimg' );
2529 $cur = wfMsg( 'cur' );
2532 $url = Image
::wfImageUrl( $img );
2534 if ( $wgUser->isSysop() ) {
2535 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2537 $style = $this->getInternalLinkAttributes( $link, $del );
2539 $dlink = '<a href="'.$link.'"'.$style.'>'.$del.'</a>';
2544 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
2545 if( $wgUser->getID() != 0 ) {
2546 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2547 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2548 urlencode( $img ) );
2549 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2550 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2552 # Having live active links for non-logged in users
2553 # means that bots and spiders crawling our site can
2554 # inadvertently change content. Baaaad idea.
2555 $rlink = wfMsg( 'revertimg' );
2560 $userlink = $usertext;
2562 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2563 ':'.$usertext, $usertext );
2565 $nbytes = wfMsg( 'nbytes', $size );
2566 $style = $this->getInternalLinkAttributes( $url, $datetime );
2568 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2569 . " . . {$userlink} ({$nbytes})";
2571 if ( '' != $description && '*' != $description ) {
2572 $sk=$wgUser->getSkin();
2573 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2579 function tocIndent($level) {
2580 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2583 function tocUnindent($level) {
2584 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2587 # parameter level defines if we are on an indentation level
2588 function tocLine( $anchor, $tocline, $level ) {
2589 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2593 return '<div class="tocline">'.$link."</div>\n";
2598 function tocTable($toc) {
2599 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2600 # try min-width & co when somebody gets a chance
2601 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2603 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2604 '<b>'.wfMsg('toc').'</b>' .
2606 '</td></tr><tr id="tocinside"><td>'."\n".
2607 $toc."</td></tr></table>\n";
2610 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2611 function editSectionScript( $section, $head ) {
2612 global $wgTitle, $wgRequest;
2613 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2616 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2617 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2620 function editSectionLink( $section ) {
2622 global $wgTitle, $wgUser, $wgLang;
2624 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2625 # Section edit links would be out of sync on an old page.
2626 # But, if we're diffing to the current page, they'll be
2631 $editurl = '§ion='.$section;
2632 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2634 if( $wgLang->isRTL() ) {
2636 $nearside = 'right';
2641 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2645 // This function is called by EditPage.php and shows a bulletin board style
2646 // toolbar for common editing functions. It can be disabled in the user preferences.
2647 // The necsesary JavaScript code can be found in style/wikibits.js.
2648 function getEditToolbar() {
2649 global $wgStylePath, $wgLang, $wgMimeType;
2651 // toolarray an array of arrays which each include the filename of
2652 // the button image (without path), the opening tag, the closing tag,
2653 // and optionally a sample text that is inserted between the two when no
2654 // selection is highlighted.
2655 // The tip text is shown when the user moves the mouse over the button.
2657 // Already here are accesskeys (key), which are not used yet until someone
2658 // can figure out a way to make them work in IE. However, we should make
2659 // sure these keys are not defined on the edit page.
2661 array( 'image'=>'button_bold.png',
2664 'sample'=>wfMsg('bold_sample'),
2665 'tip'=>wfMsg('bold_tip'),
2668 array( "image"=>"button_italic.png",
2671 "sample"=>wfMsg("italic_sample"),
2672 "tip"=>wfMsg("italic_tip"),
2675 array( "image"=>"button_link.png",
2678 "sample"=>wfMsg("link_sample"),
2679 "tip"=>wfMsg("link_tip"),
2682 array( "image"=>"button_extlink.png",
2685 "sample"=>wfMsg("extlink_sample"),
2686 "tip"=>wfMsg("extlink_tip"),
2689 array( "image"=>"button_headline.png",
2692 "sample"=>wfMsg("headline_sample"),
2693 "tip"=>wfMsg("headline_tip"),
2696 array( "image"=>"button_image.png",
2697 "open"=>"[[".$wgLang->getNsText(NS_IMAGE
).":",
2699 "sample"=>wfMsg("image_sample"),
2700 "tip"=>wfMsg("image_tip"),
2703 array( "image"=>"button_media.png",
2704 "open"=>"[[".$wgLang->getNsText(NS_MEDIA
).":",
2706 "sample"=>wfMsg("media_sample"),
2707 "tip"=>wfMsg("media_tip"),
2710 array( "image"=>"button_math.png",
2711 "open"=>"\\<math\\>",
2712 "close"=>"\\</math\\>",
2713 "sample"=>wfMsg("math_sample"),
2714 "tip"=>wfMsg("math_tip"),
2717 array( "image"=>"button_nowiki.png",
2718 "open"=>"\\<nowiki\\>",
2719 "close"=>"\\</nowiki\\>",
2720 "sample"=>wfMsg("nowiki_sample"),
2721 "tip"=>wfMsg("nowiki_tip"),
2724 array( "image"=>"button_sig.png",
2728 "tip"=>wfMsg("sig_tip"),
2731 array( "image"=>"button_hr.png",
2732 "open"=>"\\n----\\n",
2735 "tip"=>wfMsg("hr_tip"),
2739 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2741 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2742 foreach($toolarray as $tool) {
2744 $image=$wgStylePath.'/images/'.$tool['image'];
2745 $open=$tool['open'];
2746 $close=$tool['close'];
2747 $sample = addslashes( $tool['sample'] );
2749 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2750 // Older browsers show a "speedtip" type message only for ALT.
2751 // Ideally these should be different, realistically they
2752 // probably don't need to be.
2753 $tip = addslashes( $tool['tip'] );
2755 #$key = $tool["key"];
2757 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2760 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2761 $toolbar.="document.writeln(\"</div>\");\n";
2763 $toolbar.="/*]]>*/\n</script>";