3 # This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
4 if( defined( "MEDIAWIKI" ) ) {
8 require_once( 'Feed.php' ); // should not be called if the actual page isn't feed enabled
9 require_once( 'Image.php' );
11 # These are the INTERNAL names, which get mapped
12 # directly to class names. For display purposes, the
13 # Language class has internationalized names
15 /* private */ $wgValidSkinNames = array(
16 'standard' => 'Standard',
17 'nostalgia' => 'Nostalgia',
18 'cologneblue' => 'CologneBlue'
21 #$wgValidSkinNames[] = 'PHPTal';
22 #$wgValidSkinNames['davinci'] = 'DaVinci';
23 #$wgValidSkinNames['mono'] = 'Mono';
24 $wgValidSkinNames['monobook'] = 'MonoBook';
25 $wgValidSkinNames['myskin'] = 'MySkin';
26 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
27 $wgValidSkinNames['chick'] = 'Chick';
30 require_once( 'RecentChange.php' );
32 class RCCacheEntry
extends RecentChange
34 var $secureName, $link;
35 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
36 var $userlink, $timestamp, $watched;
38 function newFromParent( $rc )
40 $rc2 = new RCCacheEntry
;
41 $rc2->mAttribs
= $rc->mAttribs
;
42 $rc2->mExtra
= $rc->mExtra
;
49 /* private */ var $lastdate, $lastline;
50 var $linktrail ; # linktrail regexp
51 var $rc_cache ; # Cache for Enhanced Recent Changes
52 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
54 var $postParseLinkColour = true;
58 global $wgUseOldExistenceCheck;
59 $postParseLinkColour = !$wgUseOldExistenceCheck;
60 $this->linktrail
= wfMsg('linktrail');
63 function getSkinNames()
65 global $wgValidSkinNames;
66 return $wgValidSkinNames;
69 function getStylesheet()
71 return 'wikistandard.css';
73 function getSkinName() {
77 # Get/set accessor for delayed link colouring
78 function postParseLinkColour( $setting = NULL ) {
79 return wfSetVar( $this->postParseLinkColour
, $setting );
84 global $wgOut, $wgUser;
86 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
87 $q = $wgUser->getOption( 'quickbar' );
88 if ( '' == $q ) { $q = 0; }
92 function initPage( &$out )
94 $fname = 'Skin::initPage';
95 wfProfileIn( $fname );
97 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
99 $this->addMetadataLinks($out);
101 wfProfileOut( $fname );
104 function addMetadataLinks( &$out ) {
105 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
106 global $wgRightsPage, $wgRightsUrl;
108 if( $out->isArticleRelated() ) {
109 # note: buggy CC software only reads first "meta" link
110 if( $wgEnableCreativeCommonsRdf ) {
111 $out->addMetadataLink( array(
112 'title' => 'Creative Commons',
113 'type' => 'application/rdf+xml',
114 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
116 if( $wgEnableDublinCoreRdf ) {
117 $out->addMetadataLink( array(
118 'title' => 'Dublin Core',
119 'type' => 'application/rdf+xml',
120 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
124 if( $wgRightsPage ) {
125 $copy = Title
::newFromText( $wgRightsPage );
127 $copyright = $copy->getLocalURL();
130 if( !$copyright && $wgRightsUrl ) {
131 $copyright = $wgRightsUrl;
134 $out->addLink( array(
135 'rel' => 'copyright',
136 'href' => $copyright ) );
140 function outputPage( &$out ) {
141 global $wgDebugComments;
143 wfProfileIn( 'Skin::outputPage' );
144 $this->initPage( $out );
145 $out->out( $out->headElement() );
147 $out->out( "\n<body" );
148 $ops = $this->getBodyOptions();
149 foreach ( $ops as $name => $val ) {
150 $out->out( " $name='$val'" );
153 if ( $wgDebugComments ) {
154 $out->out( "<!-- Wiki debugging output:\n" .
155 $out->mDebugtext
. "-->\n" );
157 $out->out( $this->beforeContent() );
159 $out->out( $out->mBodytext
. "\n" );
161 $out->out( $this->afterContent() );
164 $out->out( $out->reportTime() );
166 $out->out( "\n</body></html>" );
169 function getHeadScripts() {
170 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
171 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
172 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
173 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
174 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
175 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
180 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
181 function getUserStylesheet() {
182 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
183 $sheet = $this->getStylesheet();
184 $action = $wgRequest->getText('action');
185 $s = "@import \"$wgStylePath/$sheet\";\n";
186 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
187 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
188 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
189 $s .= $wgRequest->getText('wpTextbox1');
191 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
192 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
195 $s .= $this->doGetUserStyles();
198 # placeholder, returns generated js in monobook
199 function getUserJs() {
203 function getUserStyles()
205 global $wgOut, $wgStylePath, $wgLang;
206 $s = "<style type='text/css'>\n";
207 $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
208 $s .= $this->getUserStylesheet();
209 $s .= "/*]]>*/ /* */\n";
214 function doGetUserStyles()
216 global $wgUser, $wgLang;
218 $csspage = $wgLang->getNsText( NS_MEDIAWIKI
) . ":" . $this->getSkinName() . ".css";
219 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
221 if ( 1 == $wgUser->getOption( 'underline' ) ) {
222 # Don't override browser settings
226 $s .= "a { text-decoration: none; }\n";
228 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
229 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
231 if ( 1 == $wgUser->getOption( 'justify' ) ) {
232 $s .= "#article { text-align: justify; }\n";
237 function getBodyOptions()
239 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
241 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
243 if ( 0 != $wgTitle->getNamespace() ) {
244 $a = array( 'bgcolor' => '#ffffec' );
246 else $a = array( 'bgcolor' => '#FFFFFF' );
247 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
248 (!$wgTitle->isProtected() ||
$wgUser->isSysop()) ) {
249 $t = wfMsg( 'editthispage' );
251 if ( !empty($redirect) ) {
252 $red = "&redirect={$redirect}";
254 if ( !empty($oldid) && ! isset( $diff ) ) {
255 $oid = "&oldid={$oldid}";
257 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
258 $s = 'document.location = "' .$s .'";';
259 $a +
= array ('ondblclick' => $s);
262 $a['onload'] = $wgOut->getOnloadHandler();
266 function getExternalLinkAttributes( $link, $text, $class='' )
268 global $wgUser, $wgOut, $wgLang;
270 $link = urldecode( $link );
271 $link = $wgLang->checkTitleEncoding( $link );
272 $link = str_replace( '_', ' ', $link );
273 $link = htmlspecialchars( $link );
275 $r = ($class != '') ?
" class='$class'" : " class='external'";
277 if ( 1 == $wgUser->getOption( 'hover' ) ) {
278 $r .= " title=\"{$link}\"";
283 function getInternalLinkAttributes( $link, $text, $broken = false )
285 global $wgUser, $wgOut;
287 $link = urldecode( $link );
288 $link = str_replace( '_', ' ', $link );
289 $link = htmlspecialchars( $link );
291 if ( $broken == 'stub' ) {
292 $r = ' class="stub"';
293 } else if ( $broken == 'yes' ) {
299 if ( 1 == $wgUser->getOption( 'hover' ) ) {
300 $r .= " title=\"{$link}\"";
305 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
307 global $wgUser, $wgOut;
309 if ( $broken == 'stub' ) {
310 $r = ' class="stub"';
311 } else if ( $broken == 'yes' ) {
317 if ( 1 == $wgUser->getOption( 'hover' ) ) {
318 $r .= ' title ="' . $nt->getEscapedText() . '"';
329 # This will be called immediately after the <body> tag. Split into
330 # two functions to make it easier to subclass.
332 function beforeContent()
334 global $wgUser, $wgOut;
336 return $this->doBeforeContent();
339 function doBeforeContent()
341 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
342 $fname = 'Skin::doBeforeContent';
343 wfProfileIn( $fname );
346 $qb = $this->qbSetting();
348 if( $langlinks = $this->otherLanguages() ) {
354 $borderhack = 'class="top"';
357 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
358 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
361 $left = ($qb == 1 ||
$qb == 3);
362 if($wgLang->isRTL()) $left = !$left;
365 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
366 $this->logoText() . '</td>';
368 $s .= $this->getQuickbarCompensator( $rows );
370 $l = $wgLang->isRTL() ?
'right' : 'left';
371 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
373 $s .= $this->topLinks() ;
374 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
376 $r = $wgLang->isRTL() ?
"left" : "right";
377 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
378 $s .= $this->nameAndLogin();
379 $s .= "\n<br />" . $this->searchForm() . "</td>";
382 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
385 if ( $shove && !$left ) { # Right
386 $s .= $this->getQuickbarCompensator( $rows );
388 $s .= "</tr>\n</table>\n</div>\n";
389 $s .= "\n<div id='article'>\n";
391 if( $wgSiteNotice ) {
392 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
394 $s .= $this->pageTitle();
395 $s .= $this->pageSubtitle() ;
396 $s .= $this->getCategories();
397 wfProfileOut( $fname );
401 function getCategoryLinks () {
402 global $wgOut, $wgTitle, $wgUser, $wgParser;
403 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
405 if( !$wgUseCategoryMagic ) return '' ;
406 if( count( $wgOut->mCategoryLinks
) == 0 ) return '';
408 # Taken out so that they will be displayed in previews -- TS
409 #if( !$wgOut->isArticle() ) return '';
411 $t = implode ( ' | ' , $wgOut->mCategoryLinks
) ;
412 $s = $this->makeKnownLink( 'Special:Categories',
413 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
416 # optional 'dmoz-like' category browser. Will be shown under the list
417 # of categories an article belong to
418 if($wgUseCategoryBrowser) {
421 # get a big array of the parents tree
422 $parenttree = $wgTitle->getCategorieBrowser();
424 # Render the array as a serie of links
425 function walkThrough ($tree) {
427 $sk = $wgUser->getSkin();
429 foreach($tree as $element => $parent) {
431 # element start a new list
434 # grab the others elements
435 $return .= walkThrough($parent);
437 # add our current element to the list
438 $eltitle = Title
::NewFromText($element);
439 # FIXME : should be makeLink() [AV]
440 $return .= $sk->makeKnownLink($element, $eltitle->getText()).' > ';
445 $s .= walkThrough($parenttree);
451 function getCategories() {
452 $catlinks=$this->getCategoryLinks();
453 if(!empty($catlinks)) {
454 return "<p class='catlinks'>{$catlinks}</p>";
458 function getQuickbarCompensator( $rows = 1 )
460 return "<td width='152' rowspan='{$rows}'> </td>";
463 # This gets called immediately before the </body> tag.
465 function afterContent()
467 global $wgUser, $wgOut, $wgServer;
468 global $wgTitle, $wgLang;
470 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
471 return $printfooter . $this->doAfterContent();
474 function printSource() {
476 $url = htmlspecialchars( $wgTitle->getFullURL() );
477 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
480 function printFooter() {
481 return "<p>" . $this->printSource() .
482 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
485 function doAfterContent()
487 global $wgUser, $wgOut, $wgLang;
488 $fname = 'Skin::doAfterContent';
489 wfProfileIn( $fname );
490 wfProfileIn( $fname.'-1' );
492 $s = "\n</div><br style=\"clear:both\" />\n";
493 $s .= "\n<div id='footer'>";
494 $s .= '<table border="0" cellspacing="0"><tr>';
496 wfProfileOut( $fname.'-1' );
497 wfProfileIn( $fname.'-2' );
499 $qb = $this->qbSetting();
501 $left = ($qb == 1 ||
$qb == 3);
502 if($wgLang->isRTL()) $left = !$left;
504 if ( $shove && $left ) { # Left
505 $s .= $this->getQuickbarCompensator();
507 wfProfileOut( $fname.'-2' );
508 wfProfileIn( $fname.'-3' );
509 $l = $wgLang->isRTL() ?
'right' : 'left';
510 $s .= "<td class='bottom' align='$l' valign='top'>";
512 $s .= $this->bottomLinks();
513 $s .= "\n<br />" . $this->mainPageLink()
514 . ' | ' . $this->aboutLink()
515 . ' | ' . $this->specialLink( 'recentchanges' )
516 . ' | ' . $this->searchForm()
517 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
520 if ( $shove && !$left ) { # Right
521 $s .= $this->getQuickbarCompensator();
523 $s .= "</tr></table>\n</div>\n</div>\n";
525 wfProfileOut( $fname.'-3' );
526 wfProfileIn( $fname.'-4' );
527 if ( 0 != $qb ) { $s .= $this->quickBar(); }
528 wfProfileOut( $fname.'-4' );
529 wfProfileOut( $fname );
533 function pageTitleLinks()
535 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
537 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
538 $action = $wgRequest->getText( 'action' );
540 $s = $this->printableLink();
541 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
543 if ( $wgOut->isArticleRelated() ) {
544 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
545 $name = $wgTitle->getDBkey();
546 $link = htmlspecialchars( Image
::wfImageUrl( $name ) );
547 $style = $this->getInternalLinkAttributes( $link, $name );
548 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
550 # This will show the "Approve" link if $wgUseApproval=true;
551 if ( isset ( $wgUseApproval ) && $wgUseApproval )
553 $t = $wgTitle->getDBkey();
554 $name = 'Approve this article' ;
555 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
556 #htmlspecialchars( wfImageUrl( $name ) );
557 $style = $this->getExternalLinkAttributes( $link, $name );
558 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
561 if ( 'history' == $action ||
isset( $diff ) ||
isset( $oldid ) ) {
562 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
563 wfMsg( 'currentrev' ) );
566 if ( $wgUser->getNewtalk() ) {
567 # do not show "You have new messages" text when we are viewing our
570 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
571 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
572 $n =$wgUser->getName();
573 $tl = $this->makeKnownLink( $wgLang->getNsText(
574 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
575 wfMsg('newmessageslink') );
576 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
580 $undelete = $this->getUndeleteLink();
581 if( !empty( $undelete ) ) {
582 $s .= ' | '.$undelete;
587 function getUndeleteLink() {
588 global $wgUser, $wgTitle, $wgLang, $action;
589 if( $wgUser->isSysop() &&
590 (($wgTitle->getArticleId() == 0) ||
($action == "history")) &&
591 ($n = $wgTitle->isDeleted() ) ) {
592 return wfMsg( 'thisisdeleted',
593 $this->makeKnownLink(
594 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
595 wfMsg( 'restorelink', $n ) ) );
600 function printableLink()
602 global $wgOut, $wgFeedClasses, $wgRequest;
604 $baseurl = $_SERVER['REQUEST_URI'];
605 if( strpos( '?', $baseurl ) == false ) {
610 $baseurl = htmlspecialchars( $baseurl );
611 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
613 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
614 if( $wgOut->isSyndicated() ) {
615 foreach( $wgFeedClasses as $format => $class ) {
616 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
617 $s .= " | <a href=\"$feedurl\">{$format}</a>";
625 global $wgOut, $wgTitle, $wgUser;
627 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
628 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
632 function pageSubtitle()
636 $sub = $wgOut->getSubtitle();
638 global $wgExtraSubtitle;
639 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
641 $subpages = $this->subPageSubtitle();
642 $sub .= !empty($subpages)?
"</p><p class='subpages'>$subpages":'';
643 $s = "<p class='subtitle'>{$sub}</p>\n";
647 function subPageSubtitle()
649 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
651 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
652 $ptext=$wgTitle->getPrefixedText();
653 if(preg_match('/\//',$ptext)) {
654 $links = explode('/',$ptext);
657 foreach($links as $link) {
659 if ($c<count($links)) {
660 $growinglink .= $link;
661 $getlink = $this->makeLink( $growinglink, $link );
662 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
666 $subpages .= '< ';
668 $subpages .= $getlink;
677 function nameAndLogin()
679 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
681 $li = $wgLang->specialPage( 'Userlogin' );
682 $lo = $wgLang->specialPage( 'Userlogout' );
685 if ( 0 == $wgUser->getID() ) {
686 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
689 $tl = $this->makeKnownLink( $wgLang->getNsText(
690 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
691 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
693 $s .= $n . ' ('.$tl.')';
695 $s .= wfMsg('notloggedin');
698 $rt = $wgTitle->getPrefixedURL();
699 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
701 } else { $q = "returnto={$rt}"; }
703 $s .= "\n<br />" . $this->makeKnownLink( $li,
704 wfMsg( 'login' ), $q );
706 $n = $wgUser->getName();
707 $rt = $wgTitle->getPrefixedURL();
708 $tl = $this->makeKnownLink( $wgLang->getNsText(
709 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
710 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
714 $s .= $this->makeKnownLink( $wgLang->getNsText(
715 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
716 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
717 "returnto={$rt}" ) . ' | ' .
718 $this->specialLink( 'preferences' );
720 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
726 function getSearchLink() {
727 $searchPage =& Title
::makeTitle( NS_SPECIAL
, 'Search' );
728 return $searchPage->getLocalURL();
731 function escapeSearchLink() {
732 return htmlspecialchars( $this->getSearchLink() );
735 function searchForm()
738 $search = $wgRequest->getText( 'search' );
740 $s = '<form name="search" class="inline" method="post" action="'
741 . $this->escapeSearchLink() . "\">\n"
742 . '<input type="text" name="search" size="19" value="'
743 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
744 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" /> '
745 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
755 $s = $this->mainPageLink() . $sep
756 . $this->specialLink( 'recentchanges' );
758 if ( $wgOut->isArticleRelated() ) {
759 $s .= $sep . $this->editThisPage()
760 . $sep . $this->historyLink();
762 # Many people don't like this dropdown box
763 #$s .= $sep . $this->specialPagesList();
768 function bottomLinks()
770 global $wgOut, $wgUser, $wgTitle;
774 if ( $wgOut->isArticleRelated() ) {
775 $s .= '<strong>' . $this->editThisPage() . '</strong>';
776 if ( 0 != $wgUser->getID() ) {
777 $s .= $sep . $this->watchThisPage();
779 $s .= $sep . $this->talkLink()
780 . $sep . $this->historyLink()
781 . $sep . $this->whatLinksHere()
782 . $sep . $this->watchPageLinksLink();
784 if ( $wgTitle->getNamespace() == Namespace::getUser()
785 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
788 $id=User
::idFromName($wgTitle->getText());
789 $ip=User
::isIP($wgTitle->getText());
791 if($id ||
$ip) { # both anons and non-anons have contri list
792 $s .= $sep . $this->userContribsLink();
794 if ( 0 != $wgUser->getID() ) { # show only to signed in users
795 if($id) { # can only email non-anons
796 $s .= $sep . $this->emailUserLink();
800 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
801 $s .= "\n<br />" . $this->deleteThisPage() .
802 $sep . $this->protectThisPage() .
803 $sep . $this->moveThisPage();
805 $s .= "<br />\n" . $this->otherLanguages();
812 global $wgOut, $wgLang, $wgArticle, $wgRequest;
813 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
815 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
816 if ( ! $wgOut->isArticle() ) { return ''; }
817 if ( isset( $oldid ) ||
isset( $diff ) ) { return ''; }
818 if ( 0 == $wgArticle->getID() ) { return ''; }
821 if ( !$wgDisableCounters ) {
822 $count = $wgLang->formatNum( $wgArticle->getCount() );
824 $s = wfMsg( 'viewcount', $count );
828 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
829 require_once("Credits.php");
830 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
832 $s .= $this->lastModified();
835 return $s . ' ' . $this->getCopyright();
838 function getCopyright() {
839 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
842 $oldid = $wgRequest->getVal( 'oldid' );
843 $diff = $wgRequest->getVal( 'diff' );
845 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
846 $msg = 'history_copyright';
852 if( $wgRightsPage ) {
853 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
854 } elseif( $wgRightsUrl ) {
855 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
860 $out .= wfMsg( $msg, $link );
864 function getCopyrightIcon() {
865 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
867 if( $wgRightsIcon ) {
868 $icon = htmlspecialchars( $wgRightsIcon );
870 $url = htmlspecialchars( $wgRightsUrl );
871 $out .= '<a href="'.$url.'">';
873 $text = htmlspecialchars( $wgRightsText );
874 $out .= "<img src=\"$icon\" alt='$text' />";
882 function getPoweredBy() {
884 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
885 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
889 function lastModified()
891 global $wgLang, $wgArticle;
893 $timestamp = $wgArticle->getTimestamp();
895 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
896 $s = ' ' . wfMsg( 'lastmodified', $d );
903 function logoText( $align = '' )
905 if ( '' != $align ) { $a = " align='{$align}'"; }
908 $mp = wfMsg( 'mainpage' );
909 $titleObj = Title
::newFromText( $mp );
910 if ( is_object( $titleObj ) ) {
911 $url = $titleObj->escapeLocalURL();
916 $logourl = $this->getLogo();
917 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
923 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
924 global $wgDisableUploads, $wgRemoteUploads;
926 $fname = 'Skin::quickBar';
927 wfProfileIn( $fname );
929 $action = $wgRequest->getText( 'action' );
930 $wpPreview = $wgRequest->getBool( 'wpPreview' );
931 $tns=$wgTitle->getNamespace();
933 $s = "\n<div id='quickbar'>";
934 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
937 $s .= $this->mainPageLink()
938 . $sep . $this->specialLink( 'recentchanges' )
939 . $sep . $this->specialLink( 'randompage' );
940 if ($wgUser->getID()) {
941 $s.= $sep . $this->specialLink( 'watchlist' ) ;
942 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
943 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
946 // only show watchlist link if logged in
947 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
948 $s .= "\n<br /><hr class='sep' />";
949 $articleExists = $wgTitle->getArticleId();
950 if ( $wgOut->isArticle() ||
$action =='edit' ||
$action =='history' ||
$wpPreview) {
951 if($wgOut->isArticle()) {
952 $s .= '<strong>' . $this->editThisPage() . '</strong>';
953 } else { # backlink to the article in edit or history mode
954 if($articleExists){ # no backlink if no article
957 $text = wfMsg('articlepage');
960 $text = wfMsg('viewtalkpage');
963 $text = wfMsg('userpage');
966 $text = wfMsg('viewtalkpage');
969 $text = wfMsg('wikipediapage');
972 $text = wfMsg('viewtalkpage');
975 $text = wfMsg('imagepage');
978 $text = wfMsg('viewtalkpage');
981 $text= wfMsg('articlepage');
984 $link = $wgTitle->getText();
985 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
986 $link = $nstext . ':' . $link ;
989 $s .= $this->makeLink( $link, $text );
990 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
991 # we just throw in a "New page" text to tell the user that he's in edit mode,
992 # and to avoid messing with the separator that is prepended to the next item
993 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
999 if( $tns%2
&& $action!='edit' && !$wpPreview) {
1000 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit§ion=new');
1004 watching could cause problems in edit mode:
1005 if user edits article, then loads "watch this article" in background and then saves
1006 article with "Watch this article" checkbox disabled, the article is transparently
1007 unwatched. Therefore we do not show the "Watch this page" link in edit mode
1009 if ( 0 != $wgUser->getID() && $articleExists) {
1010 if($action!='edit' && $action != 'submit' )
1012 $s .= $sep . $this->watchThisPage();
1014 if ( $wgTitle->userCanEdit() )
1015 $s .= $sep . $this->moveThisPage();
1017 if ( $wgUser->isSysop() and $articleExists ) {
1018 $s .= $sep . $this->deleteThisPage() .
1019 $sep . $this->protectThisPage();
1021 $s .= $sep . $this->talkLink();
1022 if ($articleExists && $action !='history') {
1023 $s .= $sep . $this->historyLink();
1025 $s.=$sep . $this->whatLinksHere();
1027 if($wgOut->isArticleRelated()) {
1028 $s .= $sep . $this->watchPageLinksLink();
1031 if ( Namespace::getUser() == $wgTitle->getNamespace()
1032 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1035 $id=User
::idFromName($wgTitle->getText());
1036 $ip=User
::isIP($wgTitle->getText());
1039 $s .= $sep . $this->userContribsLink();
1041 if ( 0 != $wgUser->getID() ) {
1042 if($id) { # can only email real users
1043 $s .= $sep . $this->emailUserLink();
1047 $s .= "\n<br /><hr class='sep' />";
1050 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads ||
$wgRemoteUploads ) ) {
1051 $s .= $this->specialLink( 'upload' ) . $sep;
1053 $s .= $this->specialLink( 'specialpages' )
1054 . $sep . $this->bugReportsLink();
1056 global $wgSiteSupportPage;
1057 if( $wgSiteSupportPage ) {
1058 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1059 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1062 $s .= "\n<br /></div>\n";
1063 wfProfileOut( $fname );
1067 function specialPagesList()
1069 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1070 require_once('SpecialPage.php');
1072 $pages = SpecialPage
::getPages();
1074 foreach ( $pages[''] as $name => $page ) {
1075 $a[$name] = $page->getDescription();
1077 if ( $wgUser->isSysop() )
1079 foreach ( $pages['sysop'] as $name => $page ) {
1080 $a[$name] = $page->getDescription();
1083 if ( $wgUser->isDeveloper() )
1085 foreach ( $pages['developer'] as $name => $page ) {
1086 $a[$name] = $page->getDescription() ;
1089 $go = wfMsg( 'go' );
1090 $sp = wfMsg( 'specialpages' );
1091 $spp = $wgLang->specialPage( 'Specialpages' );
1093 $s = '<form id="specialpages" method="get" class="inline" ' .
1094 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1095 $s .= "<select name=\"wpDropdown\">\n";
1096 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1098 foreach ( $a as $name => $desc ) {
1099 $p = $wgLang->specialPage( $name );
1100 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1102 $s .= "</select>\n";
1103 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1108 function mainPageLink()
1110 $mp = wfMsg( 'mainpage' );
1111 $s = $this->makeKnownLink( $mp, $mp );
1115 function copyrightLink()
1117 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1118 wfMsg( 'copyrightpagename' ) );
1122 function aboutLink()
1124 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1125 wfMsg( 'aboutwikipedia' ) );
1130 function disclaimerLink()
1132 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1133 wfMsg( 'disclaimers' ) );
1137 function editThisPage()
1139 global $wgOut, $wgTitle, $wgRequest;
1141 $oldid = $wgRequest->getVal( 'oldid' );
1142 $diff = $wgRequest->getVal( 'diff' );
1143 $redirect = $wgRequest->getVal( 'redirect' );
1145 if ( ! $wgOut->isArticleRelated() ) {
1146 $s = wfMsg( 'protectedpage' );
1148 $n = $wgTitle->getPrefixedText();
1149 if ( $wgTitle->userCanEdit() ) {
1150 $t = wfMsg( 'editthispage' );
1152 #$t = wfMsg( "protectedpage" );
1153 $t = wfMsg( 'viewsource' );
1157 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1158 if ( $oldid && ! isset( $diff ) ) {
1159 $oid = "&oldid={$oldid}";
1161 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1166 function deleteThisPage()
1168 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1170 $diff = $wgRequest->getVal( 'diff' );
1171 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1172 $n = $wgTitle->getPrefixedText();
1173 $t = wfMsg( 'deletethispage' );
1175 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1182 function protectThisPage()
1184 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1186 $diff = $wgRequest->getVal( 'diff' );
1187 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1188 $n = $wgTitle->getPrefixedText();
1190 if ( $wgTitle->isProtected() ) {
1191 $t = wfMsg( 'unprotectthispage' );
1192 $q = 'action=unprotect';
1194 $t = wfMsg( 'protectthispage' );
1195 $q = 'action=protect';
1197 $s = $this->makeKnownLink( $n, $t, $q );
1204 function watchThisPage()
1206 global $wgUser, $wgOut, $wgTitle;
1208 if ( $wgOut->isArticleRelated() ) {
1209 $n = $wgTitle->getPrefixedText();
1211 if ( $wgTitle->userIsWatching() ) {
1212 $t = wfMsg( 'unwatchthispage' );
1213 $q = 'action=unwatch';
1215 $t = wfMsg( 'watchthispage' );
1216 $q = 'action=watch';
1218 $s = $this->makeKnownLink( $n, $t, $q );
1220 $s = wfMsg( 'notanarticle' );
1225 function moveThisPage()
1227 global $wgTitle, $wgLang;
1229 if ( $wgTitle->userCanEdit() ) {
1230 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1231 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1232 } // no message if page is protected - would be redundant
1236 function historyLink()
1240 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1241 wfMsg( 'history' ), 'action=history' );
1245 function whatLinksHere()
1247 global $wgTitle, $wgLang;
1249 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1250 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1254 function userContribsLink()
1256 global $wgTitle, $wgLang;
1258 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1259 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1263 function emailUserLink()
1265 global $wgTitle, $wgLang;
1267 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1268 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1272 function watchPageLinksLink()
1274 global $wgOut, $wgTitle, $wgLang;
1276 if ( ! $wgOut->isArticleRelated() ) {
1277 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1279 $s = $this->makeKnownLink( $wgLang->specialPage(
1280 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1281 'target=' . $wgTitle->getPrefixedURL() );
1286 function otherLanguages()
1288 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1290 $a = $wgOut->getLanguageLinks();
1291 if ( 0 == count( $a ) ) {
1292 if ( !$wgUseNewInterlanguage ) return '';
1293 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1294 if ( $ns != 0 AND $ns != 1 ) return '' ;
1296 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1297 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1298 wfMsg( 'intl' ) , $x );
1301 if ( !$wgUseNewInterlanguage ) {
1302 $s = wfMsg( 'otherlanguages' ) . ': ';
1304 global $wgLanguageCode ;
1305 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1306 $x .= '&xl='.$wgLanguageCode ;
1307 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1308 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1311 $s = wfMsg( 'otherlanguages' ) . ': ';
1313 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1314 foreach( $a as $l ) {
1315 if ( ! $first ) { $s .= ' | '; }
1318 $nt = Title
::newFromText( $l );
1319 $url = $nt->getFullURL();
1320 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1322 if ( '' == $text ) { $text = $l; }
1323 $style = $this->getExternalLinkAttributes( $l, $text );
1324 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1326 if($wgLang->isRTL()) $s .= '</span>';
1330 function bugReportsLink()
1332 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1333 wfMsg( 'bugreports' ) );
1339 global $wgLinkCache;
1340 $t1 = Title
::newFromText( gmdate( 'F j' ) );
1341 $t2 = Title
::newFromText( gmdate( 'Y' ) );
1343 $wgLinkCache->suspend();
1344 $id = $t1->getArticleID();
1345 $wgLinkCache->resume();
1348 $s = $this->makeBrokenLink( $t1->getText() );
1350 $s = $this->makeKnownLink( $t1->getText() );
1354 $wgLinkCache->suspend();
1355 $id = $t2->getArticleID();
1356 $wgLinkCache->resume();
1359 $s .= $this->makeBrokenLink( $t2->getText() );
1361 $s .= $this->makeKnownLink( $t2->getText() );
1368 global $wgLang, $wgTitle, $wgLinkCache;
1370 $tns = $wgTitle->getNamespace();
1371 if ( -1 == $tns ) { return ''; }
1373 $pn = $wgTitle->getText();
1374 $tp = wfMsg( 'talkpage' );
1375 if ( Namespace::isTalk( $tns ) ) {
1376 $lns = Namespace::getSubject( $tns );
1379 $text = wfMsg('articlepage');
1382 $text = wfMsg('userpage');
1385 $text = wfMsg('wikipediapage');
1388 $text = wfMsg('imagepage');
1391 $text= wfMsg('articlepage');
1395 $lns = Namespace::getTalk( $tns );
1398 $n = $wgLang->getNsText( $lns );
1399 if ( '' == $n ) { $link = $pn; }
1400 else { $link = $n.':'.$pn; }
1402 $wgLinkCache->suspend();
1403 $s = $this->makeLink( $link, $text );
1404 $wgLinkCache->resume();
1409 function commentLink()
1411 global $wgLang, $wgTitle, $wgLinkCache;
1413 $tns = $wgTitle->getNamespace();
1414 if ( -1 == $tns ) { return ''; }
1416 $lns = ( Namespace::isTalk( $tns ) ) ?
$tns : Namespace::getTalk( $tns );
1418 # assert Namespace::isTalk( $lns )
1420 $n = $wgLang->getNsText( $lns );
1421 $pn = $wgTitle->getText();
1425 $wgLinkCache->suspend();
1426 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit§ion=new');
1427 $wgLinkCache->resume();
1432 # After all the page content is transformed into HTML, it makes
1433 # a final pass through here for things like table backgrounds.
1435 function transformContent( $text )
1440 # Note: This function MUST call getArticleID() on the link,
1441 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1443 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1444 wfProfileIn( 'Skin::makeLink' );
1445 $nt = Title
::newFromText( $title );
1447 $result = $this->makeLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1449 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1450 $result = $text == "" ?
$title : $text;
1453 wfProfileOut( 'Skin::makeLink' );
1457 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1458 $nt = Title
::newFromText( $title );
1460 return $this->makeKnownLinkObj( Title
::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1462 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1463 return $text == '' ?
$title : $text;
1467 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1468 $nt = Title
::newFromText( $title );
1470 return $this->makeBrokenLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1472 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1473 return $text == '' ?
$title : $text;
1477 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1478 $nt = Title
::newFromText( $title );
1480 return $this->makeStubLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1482 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1483 return $text == '' ?
$title : $text;
1487 # Pass a title object, not a title string
1488 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1490 global $wgOut, $wgUser;
1491 $fname = 'Skin::makeLinkObj';
1495 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1497 if ( $nt->isExternal() ) {
1498 $u = $nt->getFullURL();
1499 $link = $nt->getPrefixedURL();
1500 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1501 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1504 if ( '' != $trail ) {
1505 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1510 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1511 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1512 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1513 } elseif ( ( -1 == $nt->getNamespace() ) ||
1514 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1515 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1517 if ( $this->postParseLinkColour() ) {
1519 if ( '' != $trail ) {
1520 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1526 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1527 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1528 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1530 # Work out link colour immediately
1531 $aid = $nt->getArticleID() ;
1533 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1535 $threshold = $wgUser->getOption('stubthreshold') ;
1536 if ( $threshold > 0 ) {
1537 $dbr =& wfGetDB( DB_SLAVE
);
1538 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1539 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1540 if ( $s !== false ) {
1542 if ( $s->cur_is_redirect
OR $s->cur_namespace
!= 0 ) {
1543 $size = $threshold*2 ; # Really big
1545 $dbr->freeResult( $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 );
1563 # Pass a title object, not a title string
1564 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '' )
1566 global $wgOut, $wgTitle, $wgInputEncoding;
1568 $fname = 'Skin::makeKnownLinkObj';
1569 wfProfileIn( $fname );
1571 if ( !is_object( $nt ) ) {
1574 $link = $nt->getPrefixedURL();
1575 # if ( '' != $section && substr($section,0,1) != "#" ) {
1578 if ( '' == $link ) {
1580 if ( '' == $text ) {
1581 $text = htmlspecialchars( $nt->getFragment() );
1584 $u = $nt->escapeLocalURL( $query );
1586 if ( '' != $nt->getFragment() ) {
1587 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1588 $replacearray = array(
1592 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1594 if ( '' == $text ) {
1595 $text = htmlspecialchars( $nt->getPrefixedText() );
1597 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1600 if ( '' != $trail ) {
1601 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1606 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1607 wfProfileOut( $fname );
1611 # Pass a title object, not a title string
1612 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1614 global $wgOut, $wgUser;
1618 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1620 $fname = 'Skin::makeBrokenLinkObj';
1621 wfProfileIn( $fname );
1623 if ( '' == $query ) {
1626 $q = 'action=edit&'.$query;
1628 $u = $nt->escapeLocalURL( $q );
1630 if ( '' == $text ) {
1631 $text = htmlspecialchars( $nt->getPrefixedText() );
1633 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1636 if ( '' != $trail ) {
1637 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1642 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1643 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1645 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1648 wfProfileOut( $fname );
1652 # Pass a title object, not a title string
1653 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1655 global $wgOut, $wgUser;
1657 $link = $nt->getPrefixedURL();
1659 $u = $nt->escapeLocalURL( $query );
1661 if ( '' == $text ) {
1662 $text = htmlspecialchars( $nt->getPrefixedText() );
1664 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1667 if ( '' != $trail ) {
1668 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1673 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1674 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1676 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1681 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1683 $u = $nt->escapeLocalURL( $query );
1684 if ( '' == $text ) {
1685 $text = htmlspecialchars( $nt->getPrefixedText() );
1688 if ( '' != $trail ) {
1689 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1694 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1697 /* these are used extensively in SkinPHPTal, but also some other places */
1698 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1699 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1700 $this->checkTitle($title, $name);
1701 return $title->getLocalURL( $urlaction );
1703 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1704 $title = Title
::newFromText( $name );
1705 $title = $title->getTalkPage();
1706 $this->checkTitle($title, $name);
1707 return $title->getLocalURL( $urlaction );
1709 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1710 $title = Title
::newFromText( $name );
1711 $title= $title->getSubjectPage();
1712 $this->checkTitle($title, $name);
1713 return $title->getLocalURL( $urlaction );
1715 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1716 $title = Title
::newFromText( wfMsg($name) );
1717 $this->checkTitle($title, $name);
1718 return $title->getLocalURL( $urlaction );
1720 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1721 $title = Title
::newFromText( $name );
1722 $this->checkTitle($title, $name);
1723 return $title->getLocalURL( $urlaction );
1725 # this can be passed the NS number as defined in Language.php
1726 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1727 $title = Title
::makeTitleSafe( $namespace, $name );
1728 $this->checkTitle($title, $name);
1729 return $title->getLocalURL( $urlaction );
1732 /* these return an array with the 'href' and boolean 'exists' */
1733 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1734 $title = Title
::newFromText( $name );
1735 $this->checkTitle($title, $name);
1737 'href' => $title->getLocalURL( $urlaction ),
1738 'exists' => $title->getArticleID() != 0?
true:false
1741 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1742 $title = Title
::newFromText( $name );
1743 $title = $title->getTalkPage();
1744 $this->checkTitle($title, $name);
1746 'href' => $title->getLocalURL( $urlaction ),
1747 'exists' => $title->getArticleID() != 0?
true:false
1750 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1751 $title = Title
::newFromText( $name );
1752 $title= $title->getSubjectPage();
1753 $this->checkTitle($title, $name);
1755 'href' => $title->getLocalURL( $urlaction ),
1756 'exists' => $title->getArticleID() != 0?
true:false
1759 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1760 $title = Title
::newFromText( wfMsg($name) );
1761 $this->checkTitle($title, $name);
1763 'href' => $title->getLocalURL( $urlaction ),
1764 'exists' => $title->getArticleID() != 0?
true:false
1768 # make sure we have some title to operate on
1769 /*static*/ function checkTitle ( &$title, &$name ) {
1770 if(!is_object($title)) {
1771 $title = Title
::newFromText( $name );
1772 if(!is_object($title)) {
1773 $title = Title
::newFromText( '--error: link target missing--' );
1778 function fnamePart( $url )
1780 $basename = strrchr( $url, '/' );
1781 if ( false === $basename ) {
1784 $basename = substr( $basename, 1 );
1786 return htmlspecialchars( $basename );
1789 function makeImage( $url, $alt = '' )
1794 $alt = $this->fnamePart( $url );
1796 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1800 function makeImageLink( $name, $url, $alt = '' ) {
1801 $nt = Title
::makeTitleSafe( NS_IMAGE
, $name );
1802 return $this->makeImageLinkObj( $nt, $alt );
1805 function makeImageLinkObj( $nt, $alt = '' ) {
1806 global $wgLang, $wgUseImageResize;
1807 $img = Image
::newFromTitle( $nt );
1808 $url = $img->getURL();
1811 $prefix = $postfix = '';
1813 if ( $wgUseImageResize ) {
1814 # Check if the alt text is of the form "options|alt text"
1816 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1817 # * left no resizing, just left align. label is used for alt= only
1818 # * right same, but right aligned
1819 # * none same, but not aligned
1820 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1821 # * center center the image
1822 # * framed Keep original image size, no magnify-button.
1824 $part = explode( '|', $alt);
1826 $mwThumb =& MagicWord
::get( MAG_IMG_THUMBNAIL
);
1827 $mwLeft =& MagicWord
::get( MAG_IMG_LEFT
);
1828 $mwRight =& MagicWord
::get( MAG_IMG_RIGHT
);
1829 $mwNone =& MagicWord
::get( MAG_IMG_NONE
);
1830 $mwWidth =& MagicWord
::get( MAG_IMG_WIDTH
);
1831 $mwCenter =& MagicWord
::get( MAG_IMG_CENTER
);
1832 $mwFramed =& MagicWord
::get( MAG_IMG_FRAMED
);
1833 $alt = $part[count($part)-1];
1835 $height = $framed = $thumb = false;
1836 $manual_thumb = "" ;
1838 foreach( $part as $key => $val ) {
1839 $val_parts = explode ( "=" , $val , 2 ) ;
1840 $left_part = array_shift ( $val_parts ) ;
1841 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1843 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1844 # use manually specified thumbnail
1846 $manual_thumb = array_shift ( $val_parts ) ;
1847 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1848 # remember to set an alignment, don't render immediately
1850 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1851 # remember to set an alignment, don't render immediately
1853 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1854 # remember to set an alignment, don't render immediately
1856 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1857 # remember to set an alignment, don't render immediately
1859 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1860 # $match is the image width in pixels
1861 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1862 $width = intval( $m[1] );
1863 $height = intval( $m[2] );
1865 $width = intval($match);
1867 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1871 if ( 'center' == $align )
1873 $prefix = '<span style="text-align: center">';
1874 $postfix = '</span>';
1878 if ( $thumb ||
$framed ) {
1880 # Create a thumbnail. Alignment depends on language
1881 # writing direction, # right aligned for left-to-right-
1882 # languages ("Western languages"), left-aligned
1883 # for right-to-left-languages ("Semitic languages")
1885 # If thumbnail width has not been provided, it is set
1886 # here to 180 pixels
1887 if ( $align == '' ) {
1888 $align = $wgLang->isRTL() ?
'left' : 'right';
1890 if ( ! isset($width) ) {
1893 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1895 } elseif ( isset($width) ) {
1897 # Create a resized image, without the additional thumbnail
1900 if ( ( ! $height === false )
1901 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1902 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1903 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1904 $width = $img->getWidth() * $height / $img->getHeight();
1906 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1908 } # endif $wgUseImageResize
1910 if ( empty( $alt ) ) {
1911 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1913 $alt = htmlspecialchars( $alt );
1915 $u = $nt->escapeLocalURL();
1918 $s = wfMsg( 'missingimage', $img->getName() );
1919 $s .= "<br>{$alt}<br>{$url}<br>\n";
1921 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1922 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1924 if ( '' != $align ) {
1925 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1927 return str_replace("\n", ' ',$prefix.$s.$postfix);
1930 # Make HTML for a thumbnail including image, border and caption
1931 # $img is an Image object
1932 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1933 global $wgStylePath, $wgLang;
1934 # $image = Title::makeTitleSafe( NS_IMAGE, $name );
1935 $url = $img->getURL();
1937 #$label = htmlspecialchars( $label );
1938 $alt = preg_replace( '/<[^>]*>/', '', $label);
1939 $alt = htmlspecialchars( $alt );
1941 $width = $height = 0;
1942 if ( $img->exists() )
1944 $width = $img->getWidth();
1945 $height = $img->getHeight();
1947 if ( 0 == $width ||
0 == $height )
1949 $width = $height = 200;
1951 if ( $boxwidth == 0 )
1957 // Use image dimensions, don't scale
1959 $oboxwidth = $boxwidth +
2;
1960 $boxheight = $height;
1963 $h = intval( $height/($width/$boxwidth) );
1964 $oboxwidth = $boxwidth +
2;
1965 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1967 $boxwidth *= $boxheight/$h;
1971 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1974 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1976 $manual_title = Title
::makeTitleSafe( NS_IMAGE
, $manual_thumb ); #new Title ( $manual_thumb ) ;
1977 $manual_img = Image
::newFromTitle( $manual_title );
1978 $thumbUrl = $manual_img->getURL();
1979 if ( $manual_img->exists() )
1981 $width = $manual_img->getWidth();
1982 $height = $manual_img->getHeight();
1983 $boxwidth = $width ;
1984 $boxheight = $height ;
1985 $oboxwidth = $boxwidth +
2 ;
1989 $u = $img->getEscapeLocalURL();
1991 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1992 $magnifyalign = $wgLang->isRTL() ?
'left' : 'right';
1993 $textalign = $wgLang->isRTL() ?
' style="text-align:right"' : '';
1995 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1996 if ( $thumbUrl == '' ) {
1997 $s .= wfMsg( 'missingimage', $img->getName() );
2000 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
2001 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
2002 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
2006 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
2007 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
2008 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
2009 'width="15" height="11" alt="'.$more.'" /></a></div>';
2012 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
2013 return str_replace("\n", ' ', $s);
2016 function makeMediaLink( $name, $url, $alt = "" ) {
2017 $nt = Title
::makeTitleSafe( Namespace::getMedia(), $name );
2018 return $this->makeMediaLinkObj( $nt, $alt );
2021 function makeMediaLinkObj( $nt, $alt = "" )
2023 if ( ! isset( $nt ) )
2025 ### HOTFIX. Instead of breaking, return empty string.
2028 $name = $nt->getDBKey();
2029 $url = Image
::wfImageUrl( $name );
2030 if ( empty( $alt ) ) {
2031 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2034 $u = htmlspecialchars( $url );
2035 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2040 function specialLink( $name, $key = "" )
2044 if ( '' == $key ) { $key = strtolower( $name ); }
2045 $pn = $wgLang->ucfirst( $name );
2046 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2050 function makeExternalLink( $url, $text, $escape = true ) {
2051 $style = $this->getExternalLinkAttributes( $url, $text );
2052 $url = htmlspecialchars( $url );
2054 $text = htmlspecialchars( $text );
2056 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2059 # Called by history lists and recent changes
2062 # Returns text for the start of the tabular part of RC
2063 function beginRecentChangesList()
2065 $this->rc_cache
= array() ;
2066 $this->rcMoveIndex
= 0;
2067 $this->rcCacheIndex
= 0 ;
2068 $this->lastdate
= '';
2069 $this->rclistOpen
= false;
2073 function beginImageHistoryList()
2075 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2076 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2080 # Returns text for the end of RC
2081 # If enhanced RC is in use, returns pretty much all the text
2082 function endRecentChangesList()
2084 $s = $this->recentChangesBlock() ;
2085 if( $this->rclistOpen
) {
2091 # Enhanced RC ungrouped line
2092 function recentChangesBlockLine ( $rcObj )
2094 global $wgStylePath, $wgLang ;
2096 # Get rc_xxxx variables
2097 extract( $rcObj->mAttribs
) ;
2098 $curIdEq = 'curid='.$rc_cur_id;
2103 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2106 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2107 $r .= ' ';
2109 # M & N (minor & new)
2110 $M = wfMsg( 'minoreditletter' );
2111 $N = wfMsg( 'newpageletter' );
2113 if ( $rc_type == RC_NEW
) {
2126 $r .= ' '.$rcObj->timestamp
.' ' ;
2130 $link = $rcObj->link
;
2131 if ( $rcObj->watched
) $link = '<strong>'.$link.'</strong>' ;
2136 $r .= $rcObj->difflink
;
2140 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2143 $r .= ') . . '.$rcObj->userlink
;
2144 $r .= $rcObj->usertalklink
;
2147 if ( $rc_comment != '' && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2148 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2149 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2157 function recentChangesBlockGroup ( $block )
2159 global $wgStylePath, $wgLang ;
2162 $M = wfMsg( 'minoreditletter' );
2163 $N = wfMsg( 'newpageletter' );
2165 # Collate list of users
2167 $userlinks = array () ;
2168 foreach ( $block AS $rcObj ) {
2169 $oldid = $rcObj->mAttribs
['rc_last_oldid'];
2170 if ( $rcObj->mAttribs
['rc_new'] ) $isnew = true ;
2171 $u = $rcObj->userlink
;
2172 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2176 # Sort the list and convert to text
2177 krsort ( $userlinks ) ;
2178 asort ( $userlinks ) ;
2180 foreach ( $userlinks as $userlink => $count) {
2182 if ( $count > 1 ) $text .= " ({$count}×)" ;
2183 array_push ( $users , $text ) ;
2185 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2188 $rci = 'RCI'.$this->rcCacheIndex
;
2189 $rcl = 'RCL'.$this->rcCacheIndex
;
2190 $rcm = 'RCM'.$this->rcCacheIndex
;
2191 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2192 $arrowdir = $wgLang->isRTL() ?
'l' : 'r';
2193 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2194 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2200 if ( $isnew ) $r .= $N ;
2201 else $r .= ' ' ;
2202 $r .= ' ' ; # Minor
2205 $r .= ' '.$block[0]->timestamp
.' ' ;
2209 $link = $block[0]->link
;
2210 if ( $block[0]->watched
) $link = '<strong>'.$link.'</strong>' ;
2213 $curIdEq = 'curid=' . $block[0]->mAttribs
['rc_cur_id'];
2214 if ( $block[0]->mAttribs
['rc_type'] != RC_LOG
) {
2216 $r .= ' ('.count($block).' ' ;
2217 if ( $isnew ) $r .= wfMsg('changes');
2218 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2219 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2223 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2231 $r .= '<div id="'.$rci.'" style="display:none">' ;
2232 foreach ( $block AS $rcObj ) {
2233 # Get rc_xxxx variables
2234 extract( $rcObj->mAttribs
);
2236 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2237 $r .= '<tt> ' ;
2238 if ( $rc_new ) $r .= $N ;
2239 else $r .= ' ' ;
2240 if ( $rc_minor ) $r .= $M ;
2241 else $r .= ' ' ;
2245 if ( $rc_last_oldid != 0 ) {
2246 $o = 'oldid='.$rc_last_oldid ;
2248 if ( $rc_type == RC_LOG
) {
2249 $link = $rcObj->timestamp
;
2251 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp
, "{$curIdEq}&$o" ) ;
2253 $link = '<tt>'.$link.'</tt>' ;
2257 $r .= $rcObj->curlink
;
2259 $r .= $rcObj->lastlink
;
2260 $r .= ') . . '.$rcObj->userlink
;
2261 $r .= $rcObj->usertalklink
;
2262 if ( $rc_comment != '' ) {
2263 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2264 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2270 $this->rcCacheIndex++
;
2274 # If enhanced RC is in use, this function takes the previously cached
2275 # RC lines, arranges them, and outputs the HTML
2276 function recentChangesBlock ()
2278 global $wgStylePath ;
2279 if ( count ( $this->rc_cache
) == 0 ) return '' ;
2281 foreach ( $this->rc_cache
AS $secureName => $block ) {
2282 if ( count ( $block ) < 2 ) {
2283 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2285 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2289 return '<div>'.$blockOut.'</div>' ;
2292 # Called in a loop over all displayed RC entries
2293 # Either returns the line, or caches it for later use
2294 function recentChangesLine( &$rc, $watched = false )
2297 $usenew = $wgUser->getOption( 'usenewrc' );
2299 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2301 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2305 function recentChangesLineOld( &$rc, $watched = false )
2307 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2309 # Extract DB fields into local scope
2310 extract( $rc->mAttribs
);
2311 $curIdEq = 'curid=' . $rc_cur_id;
2313 # Make date header if necessary
2314 $date = $wgLang->date( $rc_timestamp, true);
2316 if ( $date != $this->lastdate
) {
2317 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2318 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2319 $this->lastdate
= $date;
2320 $this->rclistOpen
= true;
2323 # If this edit has not yet been patrolled, make it stick out
2324 $s .= ( ! $wgUseRCPatrol ||
$rc_patrolled ) ?
'<li> ' : '<li class="not_patrolled"> ';
2326 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2328 $s .= '(' . wfMsg( 'diff' ) . ') (';
2330 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2333 # "[[x]] moved to [[y]]"
2334 $msg = ( $rc_type == RC_MOVE
) ?
'1movedto2' : '1movedto2_redir';
2335 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2336 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2339 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2340 $diffLink = wfMsg( 'diff' );
2342 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2343 ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2344 $rcidparam = "&rcid={$rc_id}";
2347 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2348 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2349 '', '', ' tabindex="'.$rc->counter
.'"');
2351 $s .= '('.$diffLink.') (';
2354 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2357 # M and N (minor and new)
2358 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2359 if ( $rc_type == RC_NEW
) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2362 # If it's a new article, there is no diff link, but if it hasn't been
2363 # patrolled yet, we need to give users a way to do so
2364 if ( $wgUseRCPatrol && $rc_type == RC_NEW
&& $rc_patrolled == 0 &&
2365 $wgUser->getID() != 0 && ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2366 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2368 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2371 $articleLink = '<strong>'.$articleLink.'</strong>';
2373 $s .= ' '.$articleLink;
2378 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2380 # User link (or contributions for unregistered users)
2381 if ( 0 == $rc_user ) {
2382 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2383 $rc_user_text, 'target=' . $rc_user_text );
2385 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2390 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2391 global $wgDisableAnonTalk;
2392 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2395 $utns=$wgLang->getNsText(NS_USER_TALK
);
2396 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2400 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2401 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2402 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2406 if($userTalkLink) $userTalkLink .= ' | ';
2407 $userTalkLink .= $blockLink;
2409 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2412 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2413 $rc_comment=$this->formatComment($rc_comment,$rc->getTitle());
2414 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2421 function recentChangesLineNew( &$baseRC, $watched = false )
2423 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2425 # Create a specialised object
2426 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2428 # Extract fields from DB into the function scope (rc_xxxx variables)
2429 extract( $rc->mAttribs
);
2430 $curIdEq = 'curid=' . $rc_cur_id;
2432 # If it's a new day, add the headline and flush the cache
2433 $date = $wgLang->date( $rc_timestamp, true);
2435 if ( $date != $this->lastdate
) {
2436 # Process current cache
2437 $ret = $this->recentChangesBlock () ;
2438 $this->rc_cache
= array() ;
2439 $ret .= "<h4>{$date}</h4>\n";
2440 $this->lastdate
= $date;
2444 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2445 $msg = ( $rc_type == RC_MOVE
) ?
"1movedto2" : "1movedto2_redir";
2446 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2447 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2449 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2452 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2453 $rc->watched
= $watched ;
2454 $rc->link
= $clink ;
2455 $rc->timestamp
= $time;
2457 # Make "cur" and "diff" links
2458 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2459 $curLink = wfMsg( 'cur' );
2460 $diffLink = wfMsg( 'diff' );
2462 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2463 $aprops = ' tabindex="'.$baseRC->counter
.'"';
2464 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2465 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2469 $titleObj = $rc->getTitle();
2470 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2471 $lastLink = wfMsg( 'last' );
2473 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2474 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2477 # Make user link (or user contributions for unregistered users)
2478 if ( $rc_user == 0 ) {
2479 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2480 $rc_user_text, 'target=' . $rc_user_text );
2482 $userLink = $this->makeLink( $wgLang->getNsText(
2483 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2486 $rc->userlink
= $userLink;
2487 $rc->lastlink
= $lastLink;
2488 $rc->curlink
= $curLink;
2489 $rc->difflink
= $diffLink;
2491 # Make user talk link
2492 $utns=$wgLang->getNsText(NS_USER_TALK
);
2493 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2494 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2496 global $wgDisableAnonTalk;
2497 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2498 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2499 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2500 if( $wgDisableAnonTalk )
2501 $rc->usertalklink
= ' ('.$blockLink.')';
2503 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2505 if( $wgDisableAnonTalk && ($rc_user == 0) )
2506 $rc->usertalklink
= '';
2508 $rc->usertalklink
= ' ('.$userTalkLink.')';
2511 # Put accumulated information into the cache, for later display
2512 # Page moves go on their own line
2513 $title = $rc->getTitle();
2514 $secureName = $title->getPrefixedDBkey();
2515 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2516 # Use an @ character to prevent collision with page names
2517 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2519 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2520 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2525 function endImageHistoryList()
2531 /* This function is called by all recent changes variants, by the page history,
2532 and by the user contributions list. It is responsible for formatting edit
2533 comments. It escapes any HTML in the comment, but adds some CSS to format
2534 auto-generated comments (from section editing) and formats [[wikilinks]].
2536 The $title parameter, which is optional, must be a title OBJECT. It is
2537 used to generate a direct link to the section in the autocomment.
2538 Main author: Erik Moeller (moeller@scireview.de)
2540 function formatComment($comment, $title='')
2543 $comment = htmlspecialchars( $comment );
2545 # The pattern for autogen comments is / * foo * /, which makes for
2547 # We look for all comments, match any text before and after the comment,
2548 # add a separator where needed and format the comment itself with CSS
2549 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2557 # This is hackish but should work in most cases.
2558 $section=str_replace('[[','',$section);
2559 $section=str_replace(']]','',$section);
2560 $title->mFragment
=$section;
2561 $link=$this->makeKnownLinkObj($title,wfMsg('sectionlink'));
2565 if($pre) { $auto = $sep.' '.$auto; }
2566 if($post) { $auto .= ' '.$sep; }
2567 $auto='<span class="autocomment">'.$auto.'</span>';
2568 $comment=$pre.$auto.$post;
2571 # format regular and media links - all other wiki formatting
2573 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2574 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2575 # Handle link renaming [[foo|text]] will show link as "text"
2576 if( "" != $match[3] ) {
2581 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2582 # Media link; trail not supported.
2583 $linkRegexp = '/\[\[(.*?)\]\]/';
2584 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2586 # Other kind of link
2587 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2588 $trail = $submatch[1];
2592 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2593 if ($match[1][0] == ':')
2594 $match[1] = substr($match[1], 1);
2595 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2597 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2602 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2604 global $wgUser, $wgLang, $wgTitle;
2606 $datetime = $wgLang->timeanddate( $timestamp, true );
2607 $del = wfMsg( 'deleteimg' );
2608 $delall = wfMsg( 'deleteimgcompletely' );
2609 $cur = wfMsg( 'cur' );
2612 $url = Image
::wfImageUrl( $img );
2614 if ( $wgUser->isSysop() ) {
2615 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2617 $style = $this->getInternalLinkAttributes( $link, $delall );
2619 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2624 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2625 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2626 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2627 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2628 urlencode( $img ) );
2629 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2630 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2632 # Having live active links for non-logged in users
2633 # means that bots and spiders crawling our site can
2634 # inadvertently change content. Baaaad idea.
2635 $rlink = wfMsg( 'revertimg' );
2640 $userlink = $usertext;
2642 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2643 ':'.$usertext, $usertext );
2645 $nbytes = wfMsg( 'nbytes', $size );
2646 $style = $this->getInternalLinkAttributes( $url, $datetime );
2648 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2649 . " . . {$userlink} ({$nbytes})";
2651 if ( '' != $description && '*' != $description ) {
2652 $sk=$wgUser->getSkin();
2653 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2659 function tocIndent($level) {
2660 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2663 function tocUnindent($level) {
2664 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2667 # parameter level defines if we are on an indentation level
2668 function tocLine( $anchor, $tocline, $level ) {
2669 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2673 return '<div class="tocline">'.$link."</div>\n";
2678 function tocTable($toc) {
2679 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2680 # try min-width & co when somebody gets a chance
2681 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2683 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2684 '<b>'.wfMsg('toc').'</b>' .
2686 '</td></tr><tr id="tocinside"><td>'."\n".
2687 $toc."</td></tr></table>\n";
2690 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2691 function editSectionScript( $section, $head ) {
2692 global $wgTitle, $wgRequest;
2693 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2696 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2697 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2700 function editSectionLink( $section ) {
2702 global $wgTitle, $wgUser, $wgLang;
2704 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2705 # Section edit links would be out of sync on an old page.
2706 # But, if we're diffing to the current page, they'll be
2711 $editurl = '§ion='.$section;
2712 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2714 if( $wgLang->isRTL() ) {
2716 $nearside = 'right';
2721 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2725 // This function is called by EditPage.php and shows a bulletin board style
2726 // toolbar for common editing functions. It can be disabled in the user preferences.
2727 // The necsesary JavaScript code can be found in style/wikibits.js.
2728 function getEditToolbar() {
2729 global $wgStylePath, $wgLang, $wgMimeType;
2731 // toolarray an array of arrays which each include the filename of
2732 // the button image (without path), the opening tag, the closing tag,
2733 // and optionally a sample text that is inserted between the two when no
2734 // selection is highlighted.
2735 // The tip text is shown when the user moves the mouse over the button.
2737 // Already here are accesskeys (key), which are not used yet until someone
2738 // can figure out a way to make them work in IE. However, we should make
2739 // sure these keys are not defined on the edit page.
2741 array( 'image'=>'button_bold.png',
2744 'sample'=>wfMsg('bold_sample'),
2745 'tip'=>wfMsg('bold_tip'),
2748 array( "image"=>"button_italic.png",
2751 "sample"=>wfMsg("italic_sample"),
2752 "tip"=>wfMsg("italic_tip"),
2755 array( "image"=>"button_link.png",
2758 "sample"=>wfMsg("link_sample"),
2759 "tip"=>wfMsg("link_tip"),
2762 array( "image"=>"button_extlink.png",
2765 "sample"=>wfMsg("extlink_sample"),
2766 "tip"=>wfMsg("extlink_tip"),
2769 array( "image"=>"button_headline.png",
2772 "sample"=>wfMsg("headline_sample"),
2773 "tip"=>wfMsg("headline_tip"),
2776 array( "image"=>"button_image.png",
2777 "open"=>"[[".$wgLang->getNsText(NS_IMAGE
).":",
2779 "sample"=>wfMsg("image_sample"),
2780 "tip"=>wfMsg("image_tip"),
2783 array( "image"=>"button_media.png",
2784 "open"=>"[[".$wgLang->getNsText(NS_MEDIA
).":",
2786 "sample"=>wfMsg("media_sample"),
2787 "tip"=>wfMsg("media_tip"),
2790 array( "image"=>"button_math.png",
2791 "open"=>"\\<math\\>",
2792 "close"=>"\\</math\\>",
2793 "sample"=>wfMsg("math_sample"),
2794 "tip"=>wfMsg("math_tip"),
2797 array( "image"=>"button_nowiki.png",
2798 "open"=>"\\<nowiki\\>",
2799 "close"=>"\\</nowiki\\>",
2800 "sample"=>wfMsg("nowiki_sample"),
2801 "tip"=>wfMsg("nowiki_tip"),
2804 array( "image"=>"button_sig.png",
2808 "tip"=>wfMsg("sig_tip"),
2811 array( "image"=>"button_hr.png",
2812 "open"=>"\\n----\\n",
2815 "tip"=>wfMsg("hr_tip"),
2819 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2821 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2822 foreach($toolarray as $tool) {
2824 $image=$wgStylePath.'/images/'.$tool['image'];
2825 $open=$tool['open'];
2826 $close=$tool['close'];
2827 $sample = addslashes( $tool['sample'] );
2829 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2830 // Older browsers show a "speedtip" type message only for ALT.
2831 // Ideally these should be different, realistically they
2832 // probably don't need to be.
2833 $tip = addslashes( $tool['tip'] );
2835 #$key = $tool["key"];
2837 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2840 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2841 $toolbar.="document.writeln(\"</div>\");\n";
2843 $toolbar.="/*]]>*/\n</script>";
2847 /* public */ function suppressUrlExpansion() {