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();
1576 if ( '' == $link ) {
1578 if ( '' == $text ) {
1579 $text = htmlspecialchars( $nt->getFragment() );
1582 $u = $nt->escapeLocalURL( $query );
1584 if ( '' != $nt->getFragment() ) {
1585 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1586 $replacearray = array(
1590 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1592 if ( '' == $text ) {
1593 $text = htmlspecialchars( $nt->getPrefixedText() );
1595 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1598 if ( '' != $trail ) {
1599 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1604 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1605 wfProfileOut( $fname );
1609 # Pass a title object, not a title string
1610 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1612 global $wgOut, $wgUser;
1616 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1618 $fname = 'Skin::makeBrokenLinkObj';
1619 wfProfileIn( $fname );
1621 if ( '' == $query ) {
1624 $q = 'action=edit&'.$query;
1626 $u = $nt->escapeLocalURL( $q );
1628 if ( '' == $text ) {
1629 $text = htmlspecialchars( $nt->getPrefixedText() );
1631 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1634 if ( '' != $trail ) {
1635 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1640 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1641 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1643 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1646 wfProfileOut( $fname );
1650 # Pass a title object, not a title string
1651 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1653 global $wgOut, $wgUser;
1655 $link = $nt->getPrefixedURL();
1657 $u = $nt->escapeLocalURL( $query );
1659 if ( '' == $text ) {
1660 $text = htmlspecialchars( $nt->getPrefixedText() );
1662 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1665 if ( '' != $trail ) {
1666 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1671 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1672 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1674 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1679 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1681 $u = $nt->escapeLocalURL( $query );
1682 if ( '' == $text ) {
1683 $text = htmlspecialchars( $nt->getPrefixedText() );
1686 if ( '' != $trail ) {
1687 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1692 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1695 /* these are used extensively in SkinPHPTal, but also some other places */
1696 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1697 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1698 $this->checkTitle($title, $name);
1699 return $title->getLocalURL( $urlaction );
1701 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1702 $title = Title
::newFromText( $name );
1703 $title = $title->getTalkPage();
1704 $this->checkTitle($title, $name);
1705 return $title->getLocalURL( $urlaction );
1707 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1708 $title = Title
::newFromText( $name );
1709 $title= $title->getSubjectPage();
1710 $this->checkTitle($title, $name);
1711 return $title->getLocalURL( $urlaction );
1713 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1714 $title = Title
::newFromText( wfMsg($name) );
1715 $this->checkTitle($title, $name);
1716 return $title->getLocalURL( $urlaction );
1718 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1719 $title = Title
::newFromText( $name );
1720 $this->checkTitle($title, $name);
1721 return $title->getLocalURL( $urlaction );
1723 # this can be passed the NS number as defined in Language.php
1724 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1725 $title = Title
::makeTitleSafe( $namespace, $name );
1726 $this->checkTitle($title, $name);
1727 return $title->getLocalURL( $urlaction );
1730 /* these return an array with the 'href' and boolean 'exists' */
1731 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1732 $title = Title
::newFromText( $name );
1733 $this->checkTitle($title, $name);
1735 'href' => $title->getLocalURL( $urlaction ),
1736 'exists' => $title->getArticleID() != 0?
true:false
1739 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1740 $title = Title
::newFromText( $name );
1741 $title = $title->getTalkPage();
1742 $this->checkTitle($title, $name);
1744 'href' => $title->getLocalURL( $urlaction ),
1745 'exists' => $title->getArticleID() != 0?
true:false
1748 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1749 $title = Title
::newFromText( $name );
1750 $title= $title->getSubjectPage();
1751 $this->checkTitle($title, $name);
1753 'href' => $title->getLocalURL( $urlaction ),
1754 'exists' => $title->getArticleID() != 0?
true:false
1757 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1758 $title = Title
::newFromText( wfMsg($name) );
1759 $this->checkTitle($title, $name);
1761 'href' => $title->getLocalURL( $urlaction ),
1762 'exists' => $title->getArticleID() != 0?
true:false
1766 # make sure we have some title to operate on
1767 /*static*/ function checkTitle ( &$title, &$name ) {
1768 if(!is_object($title)) {
1769 $title = Title
::newFromText( $name );
1770 if(!is_object($title)) {
1771 $title = Title
::newFromText( '--error: link target missing--' );
1776 function fnamePart( $url )
1778 $basename = strrchr( $url, '/' );
1779 if ( false === $basename ) {
1782 $basename = substr( $basename, 1 );
1784 return htmlspecialchars( $basename );
1787 function makeImage( $url, $alt = '' )
1792 $alt = $this->fnamePart( $url );
1794 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1798 function makeImageLink( $name, $url, $alt = '' ) {
1799 $nt = Title
::makeTitleSafe( NS_IMAGE
, $name );
1800 return $this->makeImageLinkObj( $nt, $alt );
1803 function makeImageLinkObj( $nt, $alt = '' ) {
1804 global $wgLang, $wgUseImageResize;
1805 $img = Image
::newFromTitle( $nt );
1806 $url = $img->getURL();
1809 $prefix = $postfix = '';
1811 if ( $wgUseImageResize ) {
1812 # Check if the alt text is of the form "options|alt text"
1814 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1815 # * left no resizing, just left align. label is used for alt= only
1816 # * right same, but right aligned
1817 # * none same, but not aligned
1818 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1819 # * center center the image
1820 # * framed Keep original image size, no magnify-button.
1822 $part = explode( '|', $alt);
1824 $mwThumb =& MagicWord
::get( MAG_IMG_THUMBNAIL
);
1825 $mwLeft =& MagicWord
::get( MAG_IMG_LEFT
);
1826 $mwRight =& MagicWord
::get( MAG_IMG_RIGHT
);
1827 $mwNone =& MagicWord
::get( MAG_IMG_NONE
);
1828 $mwWidth =& MagicWord
::get( MAG_IMG_WIDTH
);
1829 $mwCenter =& MagicWord
::get( MAG_IMG_CENTER
);
1830 $mwFramed =& MagicWord
::get( MAG_IMG_FRAMED
);
1831 $alt = $part[count($part)-1];
1833 $height = $framed = $thumb = false;
1834 $manual_thumb = "" ;
1836 foreach( $part as $key => $val ) {
1837 $val_parts = explode ( "=" , $val , 2 ) ;
1838 $left_part = array_shift ( $val_parts ) ;
1839 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1841 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1842 # use manually specified thumbnail
1844 $manual_thumb = array_shift ( $val_parts ) ;
1845 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1846 # remember to set an alignment, don't render immediately
1848 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1849 # remember to set an alignment, don't render immediately
1851 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1852 # remember to set an alignment, don't render immediately
1854 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1855 # remember to set an alignment, don't render immediately
1857 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1858 # $match is the image width in pixels
1859 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1860 $width = intval( $m[1] );
1861 $height = intval( $m[2] );
1863 $width = intval($match);
1865 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1869 if ( 'center' == $align )
1871 $prefix = '<span style="text-align: center">';
1872 $postfix = '</span>';
1876 if ( $thumb ||
$framed ) {
1878 # Create a thumbnail. Alignment depends on language
1879 # writing direction, # right aligned for left-to-right-
1880 # languages ("Western languages"), left-aligned
1881 # for right-to-left-languages ("Semitic languages")
1883 # If thumbnail width has not been provided, it is set
1884 # here to 180 pixels
1885 if ( $align == '' ) {
1886 $align = $wgLang->isRTL() ?
'left' : 'right';
1888 if ( ! isset($width) ) {
1891 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1893 } elseif ( isset($width) ) {
1895 # Create a resized image, without the additional thumbnail
1898 if ( ( ! $height === false )
1899 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1900 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1901 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1902 $width = $img->getWidth() * $height / $img->getHeight();
1904 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1906 } # endif $wgUseImageResize
1908 if ( empty( $alt ) ) {
1909 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1911 $alt = htmlspecialchars( $alt );
1913 $u = $nt->escapeLocalURL();
1916 $s = wfMsg( 'missingimage', $img->getName() );
1917 $s .= "<br>{$alt}<br>{$url}<br>\n";
1919 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1920 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1922 if ( '' != $align ) {
1923 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1925 return str_replace("\n", ' ',$prefix.$s.$postfix);
1928 # Make HTML for a thumbnail including image, border and caption
1929 # $img is an Image object
1930 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1931 global $wgStylePath, $wgLang;
1932 # $image = Title::makeTitleSafe( NS_IMAGE, $name );
1933 $url = $img->getURL();
1935 #$label = htmlspecialchars( $label );
1936 $alt = preg_replace( '/<[^>]*>/', '', $label);
1937 $alt = htmlspecialchars( $alt );
1939 $width = $height = 0;
1940 if ( $img->exists() )
1942 $width = $img->getWidth();
1943 $height = $img->getHeight();
1945 if ( 0 == $width ||
0 == $height )
1947 $width = $height = 200;
1949 if ( $boxwidth == 0 )
1955 // Use image dimensions, don't scale
1957 $oboxwidth = $boxwidth +
2;
1958 $boxheight = $height;
1961 $h = intval( $height/($width/$boxwidth) );
1962 $oboxwidth = $boxwidth +
2;
1963 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1965 $boxwidth *= $boxheight/$h;
1969 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1972 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1974 $manual_title = Title
::makeTitleSafe( NS_IMAGE
, $manual_thumb ); #new Title ( $manual_thumb ) ;
1975 $manual_img = Image
::newFromTitle( $manual_title );
1976 $thumbUrl = $manual_img->getURL();
1977 if ( $manual_img->exists() )
1979 $width = $manual_img->getWidth();
1980 $height = $manual_img->getHeight();
1981 $boxwidth = $width ;
1982 $boxheight = $height ;
1983 $oboxwidth = $boxwidth +
2 ;
1987 $u = $img->getEscapeLocalURL();
1989 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1990 $magnifyalign = $wgLang->isRTL() ?
'left' : 'right';
1991 $textalign = $wgLang->isRTL() ?
' style="text-align:right"' : '';
1993 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1994 if ( $thumbUrl == '' ) {
1995 $s .= wfMsg( 'missingimage', $img->getName() );
1998 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1999 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
2000 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
2004 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
2005 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
2006 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
2007 'width="15" height="11" alt="'.$more.'" /></a></div>';
2010 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
2011 return str_replace("\n", ' ', $s);
2014 function makeMediaLink( $name, $url, $alt = "" ) {
2015 $nt = Title
::makeTitleSafe( Namespace::getMedia(), $name );
2016 return $this->makeMediaLinkObj( $nt, $alt );
2019 function makeMediaLinkObj( $nt, $alt = "" )
2021 if ( ! isset( $nt ) )
2023 ### HOTFIX. Instead of breaking, return empty string.
2026 $name = $nt->getDBKey();
2027 $url = Image
::wfImageUrl( $name );
2028 if ( empty( $alt ) ) {
2029 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2032 $u = htmlspecialchars( $url );
2033 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2038 function specialLink( $name, $key = "" )
2042 if ( '' == $key ) { $key = strtolower( $name ); }
2043 $pn = $wgLang->ucfirst( $name );
2044 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2048 function makeExternalLink( $url, $text, $escape = true ) {
2049 $style = $this->getExternalLinkAttributes( $url, $text );
2050 $url = htmlspecialchars( $url );
2052 $text = htmlspecialchars( $text );
2054 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2057 # Called by history lists and recent changes
2060 # Returns text for the start of the tabular part of RC
2061 function beginRecentChangesList()
2063 $this->rc_cache
= array() ;
2064 $this->rcMoveIndex
= 0;
2065 $this->rcCacheIndex
= 0 ;
2066 $this->lastdate
= '';
2067 $this->rclistOpen
= false;
2071 function beginImageHistoryList()
2073 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2074 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2078 # Returns text for the end of RC
2079 # If enhanced RC is in use, returns pretty much all the text
2080 function endRecentChangesList()
2082 $s = $this->recentChangesBlock() ;
2083 if( $this->rclistOpen
) {
2089 # Enhanced RC ungrouped line
2090 function recentChangesBlockLine ( $rcObj )
2092 global $wgStylePath, $wgLang ;
2094 # Get rc_xxxx variables
2095 extract( $rcObj->mAttribs
) ;
2096 $curIdEq = 'curid='.$rc_cur_id;
2101 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2104 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2105 $r .= ' ';
2107 # M & N (minor & new)
2108 $M = wfMsg( 'minoreditletter' );
2109 $N = wfMsg( 'newpageletter' );
2111 if ( $rc_type == RC_NEW
) {
2124 $r .= ' '.$rcObj->timestamp
.' ' ;
2128 $link = $rcObj->link
;
2129 if ( $rcObj->watched
) $link = '<strong>'.$link.'</strong>' ;
2134 $r .= $rcObj->difflink
;
2138 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2141 $r .= ') . . '.$rcObj->userlink
;
2142 $r .= $rcObj->usertalklink
;
2145 if ( $rc_comment != '' && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2146 $rc_comment=$this->formatComment($rc_comment);
2147 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2155 function recentChangesBlockGroup ( $block )
2157 global $wgStylePath, $wgLang ;
2160 $M = wfMsg( 'minoreditletter' );
2161 $N = wfMsg( 'newpageletter' );
2163 # Collate list of users
2165 $userlinks = array () ;
2166 foreach ( $block AS $rcObj ) {
2167 $oldid = $rcObj->mAttribs
['rc_last_oldid'];
2168 if ( $rcObj->mAttribs
['rc_new'] ) $isnew = true ;
2169 $u = $rcObj->userlink
;
2170 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2174 # Sort the list and convert to text
2175 krsort ( $userlinks ) ;
2176 asort ( $userlinks ) ;
2178 foreach ( $userlinks as $userlink => $count) {
2180 if ( $count > 1 ) $text .= " ({$count}×)" ;
2181 array_push ( $users , $text ) ;
2183 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2186 $rci = 'RCI'.$this->rcCacheIndex
;
2187 $rcl = 'RCL'.$this->rcCacheIndex
;
2188 $rcm = 'RCM'.$this->rcCacheIndex
;
2189 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2190 $arrowdir = $wgLang->isRTL() ?
'l' : 'r';
2191 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2192 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2198 if ( $isnew ) $r .= $N ;
2199 else $r .= ' ' ;
2200 $r .= ' ' ; # Minor
2203 $r .= ' '.$block[0]->timestamp
.' ' ;
2207 $link = $block[0]->link
;
2208 if ( $block[0]->watched
) $link = '<strong>'.$link.'</strong>' ;
2211 $curIdEq = 'curid=' . $block[0]->mAttribs
['rc_cur_id'];
2212 if ( $block[0]->mAttribs
['rc_type'] != RC_LOG
) {
2214 $r .= ' ('.count($block).' ' ;
2215 if ( $isnew ) $r .= wfMsg('changes');
2216 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2217 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2221 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2229 $r .= '<div id="'.$rci.'" style="display:none">' ;
2230 foreach ( $block AS $rcObj ) {
2231 # Get rc_xxxx variables
2232 extract( $rcObj->mAttribs
);
2234 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2235 $r .= '<tt> ' ;
2236 if ( $rc_new ) $r .= $N ;
2237 else $r .= ' ' ;
2238 if ( $rc_minor ) $r .= $M ;
2239 else $r .= ' ' ;
2243 if ( $rc_last_oldid != 0 ) {
2244 $o = 'oldid='.$rc_last_oldid ;
2246 if ( $rc_type == RC_LOG
) {
2247 $link = $rcObj->timestamp
;
2249 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp
, "{$curIdEq}&$o" ) ;
2251 $link = '<tt>'.$link.'</tt>' ;
2255 $r .= $rcObj->curlink
;
2257 $r .= $rcObj->lastlink
;
2258 $r .= ') . . '.$rcObj->userlink
;
2259 $r .= $rcObj->usertalklink
;
2260 if ( $rc_comment != '' ) {
2261 $rc_comment=$this->formatComment($rc_comment);
2262 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2268 $this->rcCacheIndex++
;
2272 # If enhanced RC is in use, this function takes the previously cached
2273 # RC lines, arranges them, and outputs the HTML
2274 function recentChangesBlock ()
2276 global $wgStylePath ;
2277 if ( count ( $this->rc_cache
) == 0 ) return '' ;
2279 foreach ( $this->rc_cache
AS $secureName => $block ) {
2280 if ( count ( $block ) < 2 ) {
2281 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2283 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2287 return '<div>'.$blockOut.'</div>' ;
2290 # Called in a loop over all displayed RC entries
2291 # Either returns the line, or caches it for later use
2292 function recentChangesLine( &$rc, $watched = false )
2295 $usenew = $wgUser->getOption( 'usenewrc' );
2297 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2299 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2303 function recentChangesLineOld( &$rc, $watched = false )
2305 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2307 # Extract DB fields into local scope
2308 extract( $rc->mAttribs
);
2309 $curIdEq = 'curid=' . $rc_cur_id;
2311 # Make date header if necessary
2312 $date = $wgLang->date( $rc_timestamp, true);
2314 if ( $date != $this->lastdate
) {
2315 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2316 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2317 $this->lastdate
= $date;
2318 $this->rclistOpen
= true;
2321 # If this edit has not yet been patrolled, make it stick out
2322 $s .= ( ! $wgUseRCPatrol ||
$rc_patrolled ) ?
'<li> ' : '<li class="not_patrolled"> ';
2324 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2326 $s .= '(' . wfMsg( 'diff' ) . ') (';
2328 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2331 # "[[x]] moved to [[y]]"
2332 $msg = ( $rc_type == RC_MOVE
) ?
'1movedto2' : '1movedto2_redir';
2333 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2334 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2337 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2338 $diffLink = wfMsg( 'diff' );
2340 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2341 ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2342 $rcidparam = "&rcid={$rc_id}";
2345 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2346 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2347 '', '', ' tabindex="'.$rc->counter
.'"');
2349 $s .= '('.$diffLink.') (';
2352 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2355 # M and N (minor and new)
2356 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2357 if ( $rc_type == RC_NEW
) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2360 # If it's a new article, there is no diff link, but if it hasn't been
2361 # patrolled yet, we need to give users a way to do so
2362 if ( $wgUseRCPatrol && $rc_type == RC_NEW
&& $rc_patrolled == 0 &&
2363 $wgUser->getID() != 0 && ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2364 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2366 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2369 $articleLink = '<strong>'.$articleLink.'</strong>';
2371 $s .= ' '.$articleLink;
2376 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2378 # User link (or contributions for unregistered users)
2379 if ( 0 == $rc_user ) {
2380 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2381 $rc_user_text, 'target=' . $rc_user_text );
2383 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2388 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2389 global $wgDisableAnonTalk;
2390 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2393 $utns=$wgLang->getNsText(NS_USER_TALK
);
2394 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2398 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2399 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2400 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2404 if($userTalkLink) $userTalkLink .= ' | ';
2405 $userTalkLink .= $blockLink;
2407 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2410 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2411 $rc_comment=$this->formatComment($rc_comment);
2412 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2419 function recentChangesLineNew( &$baseRC, $watched = false )
2421 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2423 # Create a specialised object
2424 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2426 # Extract fields from DB into the function scope (rc_xxxx variables)
2427 extract( $rc->mAttribs
);
2428 $curIdEq = 'curid=' . $rc_cur_id;
2430 # If it's a new day, add the headline and flush the cache
2431 $date = $wgLang->date( $rc_timestamp, true);
2433 if ( $date != $this->lastdate
) {
2434 # Process current cache
2435 $ret = $this->recentChangesBlock () ;
2436 $this->rc_cache
= array() ;
2437 $ret .= "<h4>{$date}</h4>\n";
2438 $this->lastdate
= $date;
2442 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2443 $msg = ( $rc_type == RC_MOVE
) ?
"1movedto2" : "1movedto2_redir";
2444 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2445 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2447 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2450 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2451 $rc->watched
= $watched ;
2452 $rc->link
= $clink ;
2453 $rc->timestamp
= $time;
2455 # Make "cur" and "diff" links
2456 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2457 $curLink = wfMsg( 'cur' );
2458 $diffLink = wfMsg( 'diff' );
2460 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2461 $aprops = ' tabindex="'.$baseRC->counter
.'"';
2462 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2463 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2467 $titleObj = $rc->getTitle();
2468 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2469 $lastLink = wfMsg( 'last' );
2471 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2472 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2475 # Make user link (or user contributions for unregistered users)
2476 if ( $rc_user == 0 ) {
2477 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2478 $rc_user_text, 'target=' . $rc_user_text );
2480 $userLink = $this->makeLink( $wgLang->getNsText(
2481 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2484 $rc->userlink
= $userLink;
2485 $rc->lastlink
= $lastLink;
2486 $rc->curlink
= $curLink;
2487 $rc->difflink
= $diffLink;
2489 # Make user talk link
2490 $utns=$wgLang->getNsText(NS_USER_TALK
);
2491 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2492 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2494 global $wgDisableAnonTalk;
2495 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2496 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2497 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2498 if( $wgDisableAnonTalk )
2499 $rc->usertalklink
= ' ('.$blockLink.')';
2501 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2503 if( $wgDisableAnonTalk && ($rc_user == 0) )
2504 $rc->usertalklink
= '';
2506 $rc->usertalklink
= ' ('.$userTalkLink.')';
2509 # Put accumulated information into the cache, for later display
2510 # Page moves go on their own line
2511 $title = $rc->getTitle();
2512 $secureName = $title->getPrefixedDBkey();
2513 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2514 # Use an @ character to prevent collision with page names
2515 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2517 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2518 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2523 function endImageHistoryList()
2529 /* This function is called by all recent changes variants, by the page history,
2530 and by the user contributions list. It is responsible for formatting edit
2531 comments. It escapes any HTML in the comment, but adds some CSS to format
2532 auto-generated comments (from section editing) and formats [[wikilinks]].
2533 Main author: Erik Möller (moeller@scireview.de)
2535 function formatComment($comment)
2538 $comment = htmlspecialchars( $comment );
2540 # The pattern for autogen comments is / * foo * /, which makes for
2542 # We look for all comments, match any text before and after the comment,
2543 # add a separator where needed and format the comment itself with CSS
2544 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2549 if($pre) { $auto = $sep.' '.$auto; }
2550 if($post) { $auto .= ' '.$sep; }
2551 $auto='<span class="autocomment">'.$auto.'</span>';
2552 $comment=$pre.$auto.$post;
2555 # format regular and media links - all other wiki formatting
2557 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2558 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2559 # Handle link renaming [[foo|text]] will show link as "text"
2560 if( "" != $match[3] ) {
2565 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2566 # Media link; trail not supported.
2567 $linkRegexp = '/\[\[(.*?)\]\]/';
2568 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2570 # Other kind of link
2571 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2572 $trail = $submatch[1];
2576 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2577 if ($match[1][0] == ':')
2578 $match[1] = substr($match[1], 1);
2579 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2581 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2586 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2588 global $wgUser, $wgLang, $wgTitle;
2590 $datetime = $wgLang->timeanddate( $timestamp, true );
2591 $del = wfMsg( 'deleteimg' );
2592 $delall = wfMsg( 'deleteimgcompletely' );
2593 $cur = wfMsg( 'cur' );
2596 $url = Image
::wfImageUrl( $img );
2598 if ( $wgUser->isSysop() ) {
2599 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2601 $style = $this->getInternalLinkAttributes( $link, $delall );
2603 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2608 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2609 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2610 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2611 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2612 urlencode( $img ) );
2613 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2614 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2616 # Having live active links for non-logged in users
2617 # means that bots and spiders crawling our site can
2618 # inadvertently change content. Baaaad idea.
2619 $rlink = wfMsg( 'revertimg' );
2624 $userlink = $usertext;
2626 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2627 ':'.$usertext, $usertext );
2629 $nbytes = wfMsg( 'nbytes', $size );
2630 $style = $this->getInternalLinkAttributes( $url, $datetime );
2632 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2633 . " . . {$userlink} ({$nbytes})";
2635 if ( '' != $description && '*' != $description ) {
2636 $sk=$wgUser->getSkin();
2637 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2643 function tocIndent($level) {
2644 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2647 function tocUnindent($level) {
2648 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2651 # parameter level defines if we are on an indentation level
2652 function tocLine( $anchor, $tocline, $level ) {
2653 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2657 return '<div class="tocline">'.$link."</div>\n";
2662 function tocTable($toc) {
2663 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2664 # try min-width & co when somebody gets a chance
2665 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2667 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2668 '<b>'.wfMsg('toc').'</b>' .
2670 '</td></tr><tr id="tocinside"><td>'."\n".
2671 $toc."</td></tr></table>\n";
2674 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2675 function editSectionScript( $section, $head ) {
2676 global $wgTitle, $wgRequest;
2677 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2680 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2681 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2684 function editSectionLink( $section ) {
2686 global $wgTitle, $wgUser, $wgLang;
2688 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2689 # Section edit links would be out of sync on an old page.
2690 # But, if we're diffing to the current page, they'll be
2695 $editurl = '§ion='.$section;
2696 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2698 if( $wgLang->isRTL() ) {
2700 $nearside = 'right';
2705 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2709 // This function is called by EditPage.php and shows a bulletin board style
2710 // toolbar for common editing functions. It can be disabled in the user preferences.
2711 // The necsesary JavaScript code can be found in style/wikibits.js.
2712 function getEditToolbar() {
2713 global $wgStylePath, $wgLang, $wgMimeType;
2715 // toolarray an array of arrays which each include the filename of
2716 // the button image (without path), the opening tag, the closing tag,
2717 // and optionally a sample text that is inserted between the two when no
2718 // selection is highlighted.
2719 // The tip text is shown when the user moves the mouse over the button.
2721 // Already here are accesskeys (key), which are not used yet until someone
2722 // can figure out a way to make them work in IE. However, we should make
2723 // sure these keys are not defined on the edit page.
2725 array( 'image'=>'button_bold.png',
2728 'sample'=>wfMsg('bold_sample'),
2729 'tip'=>wfMsg('bold_tip'),
2732 array( "image"=>"button_italic.png",
2735 "sample"=>wfMsg("italic_sample"),
2736 "tip"=>wfMsg("italic_tip"),
2739 array( "image"=>"button_link.png",
2742 "sample"=>wfMsg("link_sample"),
2743 "tip"=>wfMsg("link_tip"),
2746 array( "image"=>"button_extlink.png",
2749 "sample"=>wfMsg("extlink_sample"),
2750 "tip"=>wfMsg("extlink_tip"),
2753 array( "image"=>"button_headline.png",
2756 "sample"=>wfMsg("headline_sample"),
2757 "tip"=>wfMsg("headline_tip"),
2760 array( "image"=>"button_image.png",
2761 "open"=>"[[".$wgLang->getNsText(NS_IMAGE
).":",
2763 "sample"=>wfMsg("image_sample"),
2764 "tip"=>wfMsg("image_tip"),
2767 array( "image"=>"button_media.png",
2768 "open"=>"[[".$wgLang->getNsText(NS_MEDIA
).":",
2770 "sample"=>wfMsg("media_sample"),
2771 "tip"=>wfMsg("media_tip"),
2774 array( "image"=>"button_math.png",
2775 "open"=>"\\<math\\>",
2776 "close"=>"\\</math\\>",
2777 "sample"=>wfMsg("math_sample"),
2778 "tip"=>wfMsg("math_tip"),
2781 array( "image"=>"button_nowiki.png",
2782 "open"=>"\\<nowiki\\>",
2783 "close"=>"\\</nowiki\\>",
2784 "sample"=>wfMsg("nowiki_sample"),
2785 "tip"=>wfMsg("nowiki_tip"),
2788 array( "image"=>"button_sig.png",
2792 "tip"=>wfMsg("sig_tip"),
2795 array( "image"=>"button_hr.png",
2796 "open"=>"\\n----\\n",
2799 "tip"=>wfMsg("hr_tip"),
2803 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2805 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2806 foreach($toolarray as $tool) {
2808 $image=$wgStylePath.'/images/'.$tool['image'];
2809 $open=$tool['open'];
2810 $close=$tool['close'];
2811 $sample = addslashes( $tool['sample'] );
2813 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2814 // Older browsers show a "speedtip" type message only for ALT.
2815 // Ideally these should be different, realistically they
2816 // probably don't need to be.
2817 $tip = addslashes( $tool['tip'] );
2819 #$key = $tool["key"];
2821 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2824 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2825 $toolbar.="document.writeln(\"</div>\");\n";
2827 $toolbar.="/*]]>*/\n</script>";
2831 /* public */ function suppressUrlExpansion() {