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 directly to class names and
12 # file names in ./skins/. For display purposes, the Language class has
13 # internationalized names
16 $wgValidSkinNames = array(
17 'standard' => 'Standard',
18 'nostalgia' => 'Nostalgia',
19 'cologneblue' => 'CologneBlue'
22 #$wgValidSkinNames[] = 'PHPTal';
23 #$wgValidSkinNames['davinci'] = 'DaVinci';
24 #$wgValidSkinNames['mono'] = 'Mono';
25 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
26 $wgValidSkinNames['monobook'] = 'MonoBook';
27 $wgValidSkinNames['myskin'] = 'MySkin';
28 $wgValidSkinNames['chick'] = 'Chick';
32 # Get a list of all skins available in /skins/
33 # Build using the regular expression '^(.*).php$'
34 # Array keys are all lower case, array value keep the case used by filename
37 $skinDir = dir($IP.'/skins');
39 # while code from www.php.net
40 while (false !== ($file = $skinDir->read())) {
41 if(preg_match('/^(.*).php$/',$file, $matches)) {
43 $wgValidSkinNames[strtolower($aSkin)] = $aSkin;
49 require_once( 'RecentChange.php' );
51 class RCCacheEntry
extends RecentChange
53 var $secureName, $link;
54 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
55 var $userlink, $timestamp, $watched;
57 function newFromParent( $rc )
59 $rc2 = new RCCacheEntry
;
60 $rc2->mAttribs
= $rc->mAttribs
;
61 $rc2->mExtra
= $rc->mExtra
;
67 # The main skin class that provide methods and properties for all other skins
68 # including PHPTal skins.
69 # This base class is also the "Standard" skin.
73 /* private */ var $lastdate, $lastline;
74 var $linktrail ; # linktrail regexp
75 var $rc_cache ; # Cache for Enhanced Recent Changes
76 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
78 var $postParseLinkColour = true;
81 global $wgUseOldExistenceCheck;
82 $postParseLinkColour = !$wgUseOldExistenceCheck;
83 $this->linktrail
= wfMsg('linktrail');
86 function getSkinNames() {
87 global $wgValidSkinNames;
88 return $wgValidSkinNames;
91 function getStylesheet() {
92 return 'wikistandard.css';
95 function getSkinName() {
99 # Get/set accessor for delayed link colouring
100 function postParseLinkColour( $setting = NULL ) {
101 return wfSetVar( $this->postParseLinkColour
, $setting );
104 function qbSetting() {
105 global $wgOut, $wgUser;
107 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
108 $q = $wgUser->getOption( 'quickbar' );
109 if ( '' == $q ) { $q = 0; }
113 function initPage( &$out ) {
114 $fname = 'Skin::initPage';
115 wfProfileIn( $fname );
117 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
119 $this->addMetadataLinks($out);
121 wfProfileOut( $fname );
124 function addMetadataLinks( &$out ) {
125 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
126 global $wgRightsPage, $wgRightsUrl;
128 if( $out->isArticleRelated() ) {
129 # note: buggy CC software only reads first "meta" link
130 if( $wgEnableCreativeCommonsRdf ) {
131 $out->addMetadataLink( array(
132 'title' => 'Creative Commons',
133 'type' => 'application/rdf+xml',
134 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
136 if( $wgEnableDublinCoreRdf ) {
137 $out->addMetadataLink( array(
138 'title' => 'Dublin Core',
139 'type' => 'application/rdf+xml',
140 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
144 if( $wgRightsPage ) {
145 $copy = Title
::newFromText( $wgRightsPage );
147 $copyright = $copy->getLocalURL();
150 if( !$copyright && $wgRightsUrl ) {
151 $copyright = $wgRightsUrl;
154 $out->addLink( array(
155 'rel' => 'copyright',
156 'href' => $copyright ) );
160 function outputPage( &$out ) {
161 global $wgDebugComments;
163 wfProfileIn( 'Skin::outputPage' );
164 $this->initPage( $out );
165 $out->out( $out->headElement() );
167 $out->out( "\n<body" );
168 $ops = $this->getBodyOptions();
169 foreach ( $ops as $name => $val ) {
170 $out->out( " $name='$val'" );
173 if ( $wgDebugComments ) {
174 $out->out( "<!-- Wiki debugging output:\n" .
175 $out->mDebugtext
. "-->\n" );
177 $out->out( $this->beforeContent() );
179 $out->out( $out->mBodytext
. "\n" );
181 $out->out( $this->afterContent() );
184 $out->out( $out->reportTime() );
186 $out->out( "\n</body></html>" );
189 function getHeadScripts() {
190 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
191 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
192 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
193 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
194 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
195 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
200 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
201 function getUserStylesheet() {
202 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
203 $sheet = $this->getStylesheet();
204 $action = $wgRequest->getText('action');
205 $s = "@import \"$wgStylePath/$sheet\";\n";
206 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
207 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
208 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
209 $s .= $wgRequest->getText('wpTextbox1');
211 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
212 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
215 $s .= $this->doGetUserStyles();
219 # placeholder, returns generated js in monobook
220 function getUserJs() { return; }
222 # Return html code that include User stylesheets
223 function getUserStyles() {
224 global $wgOut, $wgStylePath, $wgLang;
225 $s = "<style type='text/css'>\n";
226 $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
227 $s .= $this->getUserStylesheet();
228 $s .= "/*]]>*/ /* */\n";
233 # Some styles that are set by user through the user settings interface.
234 function doGetUserStyles() {
235 global $wgUser, $wgLang;
237 $csspage = $wgLang->getNsText( NS_MEDIAWIKI
) . ':' . $this->getSkinName() . '.css';
238 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
240 if ( 1 == $wgUser->getOption( 'underline' ) ) {
241 # Don't override browser settings
245 $s .= "a { text-decoration: none; }\n";
247 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
248 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
250 if ( 1 == $wgUser->getOption( 'justify' ) ) {
251 $s .= "#article { text-align: justify; }\n";
256 function getBodyOptions()
258 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
260 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
262 if ( 0 != $wgTitle->getNamespace() ) {
263 $a = array( 'bgcolor' => '#ffffec' );
265 else $a = array( 'bgcolor' => '#FFFFFF' );
266 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
267 (!$wgTitle->isProtected() ||
$wgUser->isSysop()) ) {
268 $t = wfMsg( 'editthispage' );
270 if ( !empty($redirect) ) {
271 $red = "&redirect={$redirect}";
273 if ( !empty($oldid) && ! isset( $diff ) ) {
274 $oid = "&oldid={$oldid}";
276 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
277 $s = 'document.location = "' .$s .'";';
278 $a +
= array ('ondblclick' => $s);
281 $a['onload'] = $wgOut->getOnloadHandler();
285 function getExternalLinkAttributes( $link, $text, $class='' )
287 global $wgUser, $wgOut, $wgLang;
289 $link = urldecode( $link );
290 $link = $wgLang->checkTitleEncoding( $link );
291 $link = str_replace( '_', ' ', $link );
292 $link = htmlspecialchars( $link );
294 $r = ($class != '') ?
" class='$class'" : " class='external'";
296 if ( 1 == $wgUser->getOption( 'hover' ) ) {
297 $r .= " title=\"{$link}\"";
302 function getInternalLinkAttributes( $link, $text, $broken = false )
304 global $wgUser, $wgOut;
306 $link = urldecode( $link );
307 $link = str_replace( '_', ' ', $link );
308 $link = htmlspecialchars( $link );
310 if ( $broken == 'stub' ) {
311 $r = ' class="stub"';
312 } else if ( $broken == 'yes' ) {
318 if ( 1 == $wgUser->getOption( 'hover' ) ) {
319 $r .= " title=\"{$link}\"";
324 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
326 global $wgUser, $wgOut;
328 if ( $broken == 'stub' ) {
329 $r = ' class="stub"';
330 } else if ( $broken == 'yes' ) {
336 if ( 1 == $wgUser->getOption( 'hover' ) ) {
337 $r .= ' title ="' . $nt->getEscapedText() . '"';
348 # This will be called immediately after the <body> tag. Split into
349 # two functions to make it easier to subclass.
351 function beforeContent()
353 global $wgUser, $wgOut;
355 return $this->doBeforeContent();
358 function doBeforeContent()
360 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
361 $fname = 'Skin::doBeforeContent';
362 wfProfileIn( $fname );
365 $qb = $this->qbSetting();
367 if( $langlinks = $this->otherLanguages() ) {
373 $borderhack = 'class="top"';
376 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
377 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
380 $left = ($qb == 1 ||
$qb == 3);
381 if($wgLang->isRTL()) $left = !$left;
384 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
385 $this->logoText() . '</td>';
387 $s .= $this->getQuickbarCompensator( $rows );
389 $l = $wgLang->isRTL() ?
'right' : 'left';
390 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
392 $s .= $this->topLinks() ;
393 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
395 $r = $wgLang->isRTL() ?
"left" : "right";
396 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
397 $s .= $this->nameAndLogin();
398 $s .= "\n<br />" . $this->searchForm() . "</td>";
401 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
404 if ( $shove && !$left ) { # Right
405 $s .= $this->getQuickbarCompensator( $rows );
407 $s .= "</tr>\n</table>\n</div>\n";
408 $s .= "\n<div id='article'>\n";
410 if( $wgSiteNotice ) {
411 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
413 $s .= $this->pageTitle();
414 $s .= $this->pageSubtitle() ;
415 $s .= $this->getCategories();
416 wfProfileOut( $fname );
420 function getCategoryLinks () {
421 global $wgOut, $wgTitle, $wgUser, $wgParser;
422 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
424 if( !$wgUseCategoryMagic ) return '' ;
425 if( count( $wgOut->mCategoryLinks
) == 0 ) return '';
427 # Taken out so that they will be displayed in previews -- TS
428 #if( !$wgOut->isArticle() ) return '';
430 $t = implode ( ' | ' , $wgOut->mCategoryLinks
) ;
431 $s = $this->makeKnownLink( 'Special:Categories',
432 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
435 # optional 'dmoz-like' category browser. Will be shown under the list
436 # of categories an article belong to
437 if($wgUseCategoryBrowser) {
440 # get a big array of the parents tree
441 $parenttree = $wgTitle->getCategorieBrowser();
443 # Render the array as a serie of links
444 function walkThrough ($tree) {
446 $sk = $wgUser->getSkin();
448 foreach($tree as $element => $parent) {
450 # element start a new list
453 # grab the others elements
454 $return .= walkThrough($parent);
456 # add our current element to the list
457 $eltitle = Title
::NewFromText($element);
458 # FIXME : should be makeLink() [AV]
459 $return .= $sk->makeKnownLink($element, $eltitle->getText()).' > ';
464 $s .= walkThrough($parenttree);
470 function getCategories() {
471 $catlinks=$this->getCategoryLinks();
472 if(!empty($catlinks)) {
473 return "<p class='catlinks'>{$catlinks}</p>";
477 function getQuickbarCompensator( $rows = 1 ) {
478 return "<td width='152' rowspan='{$rows}'> </td>";
481 # This gets called immediately before the </body> tag.
483 function afterContent() {
484 global $wgUser, $wgOut, $wgServer;
485 global $wgTitle, $wgLang;
487 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
488 return $printfooter . $this->doAfterContent();
491 function printSource() {
493 $url = htmlspecialchars( $wgTitle->getFullURL() );
494 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
497 function printFooter() {
498 return "<p>" . $this->printSource() .
499 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
502 function doAfterContent() {
503 global $wgUser, $wgOut, $wgLang;
504 $fname = 'Skin::doAfterContent';
505 wfProfileIn( $fname );
506 wfProfileIn( $fname.'-1' );
508 $s = "\n</div><br style=\"clear:both\" />\n";
509 $s .= "\n<div id='footer'>";
510 $s .= '<table border="0" cellspacing="0"><tr>';
512 wfProfileOut( $fname.'-1' );
513 wfProfileIn( $fname.'-2' );
515 $qb = $this->qbSetting();
517 $left = ($qb == 1 ||
$qb == 3);
518 if($wgLang->isRTL()) $left = !$left;
520 if ( $shove && $left ) { # Left
521 $s .= $this->getQuickbarCompensator();
523 wfProfileOut( $fname.'-2' );
524 wfProfileIn( $fname.'-3' );
525 $l = $wgLang->isRTL() ?
'right' : 'left';
526 $s .= "<td class='bottom' align='$l' valign='top'>";
528 $s .= $this->bottomLinks();
529 $s .= "\n<br />" . $this->mainPageLink()
530 . ' | ' . $this->aboutLink()
531 . ' | ' . $this->specialLink( 'recentchanges' )
532 . ' | ' . $this->searchForm()
533 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
536 if ( $shove && !$left ) { # Right
537 $s .= $this->getQuickbarCompensator();
539 $s .= "</tr></table>\n</div>\n</div>\n";
541 wfProfileOut( $fname.'-3' );
542 wfProfileIn( $fname.'-4' );
543 if ( 0 != $qb ) { $s .= $this->quickBar(); }
544 wfProfileOut( $fname.'-4' );
545 wfProfileOut( $fname );
549 function pageTitleLinks() {
550 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
552 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
553 $action = $wgRequest->getText( 'action' );
555 $s = $this->printableLink();
556 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
558 if ( $wgOut->isArticleRelated() ) {
559 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
560 $name = $wgTitle->getDBkey();
561 $link = htmlspecialchars( Image
::wfImageUrl( $name ) );
562 $style = $this->getInternalLinkAttributes( $link, $name );
563 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
565 # This will show the "Approve" link if $wgUseApproval=true;
566 if ( isset ( $wgUseApproval ) && $wgUseApproval )
568 $t = $wgTitle->getDBkey();
569 $name = 'Approve this article' ;
570 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
571 #htmlspecialchars( wfImageUrl( $name ) );
572 $style = $this->getExternalLinkAttributes( $link, $name );
573 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
576 if ( 'history' == $action ||
isset( $diff ) ||
isset( $oldid ) ) {
577 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
578 wfMsg( 'currentrev' ) );
581 if ( $wgUser->getNewtalk() ) {
582 # do not show "You have new messages" text when we are viewing our
585 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
586 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
587 $n =$wgUser->getName();
588 $tl = $this->makeKnownLink( $wgLang->getNsText(
589 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
590 wfMsg('newmessageslink') );
591 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
593 $wgOut->setSquidMaxage(0);
597 $undelete = $this->getUndeleteLink();
598 if( !empty( $undelete ) ) {
599 $s .= ' | '.$undelete;
604 function getUndeleteLink() {
605 global $wgUser, $wgTitle, $wgLang, $action;
606 if( $wgUser->isSysop() &&
607 (($wgTitle->getArticleId() == 0) ||
($action == "history")) &&
608 ($n = $wgTitle->isDeleted() ) ) {
609 return wfMsg( 'thisisdeleted',
610 $this->makeKnownLink(
611 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
612 wfMsg( 'restorelink', $n ) ) );
617 function printableLink() {
618 global $wgOut, $wgFeedClasses, $wgRequest;
620 $baseurl = $_SERVER['REQUEST_URI'];
621 if( strpos( '?', $baseurl ) == false ) {
626 $baseurl = htmlspecialchars( $baseurl );
627 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
629 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
630 if( $wgOut->isSyndicated() ) {
631 foreach( $wgFeedClasses as $format => $class ) {
632 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
633 $s .= " | <a href=\"$feedurl\">{$format}</a>";
639 function pageTitle() {
640 global $wgOut, $wgTitle, $wgUser;
642 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
643 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
647 function pageSubtitle() {
650 $sub = $wgOut->getSubtitle();
652 global $wgExtraSubtitle;
653 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
655 $subpages = $this->subPageSubtitle();
656 $sub .= !empty($subpages)?
"</p><p class='subpages'>$subpages":'';
657 $s = "<p class='subtitle'>{$sub}</p>\n";
661 function subPageSubtitle() {
662 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
664 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
665 $ptext=$wgTitle->getPrefixedText();
666 if(preg_match('/\//',$ptext)) {
667 $links = explode('/',$ptext);
670 foreach($links as $link) {
672 if ($c<count($links)) {
673 $growinglink .= $link;
674 $getlink = $this->makeLink( $growinglink, $link );
675 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
679 $subpages .= '< ';
681 $subpages .= $getlink;
690 function nameAndLogin() {
691 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
693 $li = $wgLang->specialPage( 'Userlogin' );
694 $lo = $wgLang->specialPage( 'Userlogout' );
697 if ( 0 == $wgUser->getID() ) {
698 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
701 $tl = $this->makeKnownLink( $wgLang->getNsText(
702 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
703 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
705 $s .= $n . ' ('.$tl.')';
707 $s .= wfMsg('notloggedin');
710 $rt = $wgTitle->getPrefixedURL();
711 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
713 } else { $q = "returnto={$rt}"; }
715 $s .= "\n<br />" . $this->makeKnownLink( $li,
716 wfMsg( 'login' ), $q );
718 $n = $wgUser->getName();
719 $rt = $wgTitle->getPrefixedURL();
720 $tl = $this->makeKnownLink( $wgLang->getNsText(
721 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
722 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
726 $s .= $this->makeKnownLink( $wgLang->getNsText(
727 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
728 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
729 "returnto={$rt}" ) . ' | ' .
730 $this->specialLink( 'preferences' );
732 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
738 function getSearchLink() {
739 $searchPage =& Title
::makeTitle( NS_SPECIAL
, 'Search' );
740 return $searchPage->getLocalURL();
743 function escapeSearchLink() {
744 return htmlspecialchars( $this->getSearchLink() );
747 function searchForm() {
749 $search = $wgRequest->getText( 'search' );
751 $s = '<form name="search" class="inline" method="post" action="'
752 . $this->escapeSearchLink() . "\">\n"
753 . '<input type="text" name="search" size="19" value="'
754 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
755 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" /> '
756 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
761 function topLinks() {
765 $s = $this->mainPageLink() . $sep
766 . $this->specialLink( 'recentchanges' );
768 if ( $wgOut->isArticleRelated() ) {
769 $s .= $sep . $this->editThisPage()
770 . $sep . $this->historyLink();
772 # Many people don't like this dropdown box
773 #$s .= $sep . $this->specialPagesList();
778 function bottomLinks() {
779 global $wgOut, $wgUser, $wgTitle;
783 if ( $wgOut->isArticleRelated() ) {
784 $s .= '<strong>' . $this->editThisPage() . '</strong>';
785 if ( 0 != $wgUser->getID() ) {
786 $s .= $sep . $this->watchThisPage();
788 $s .= $sep . $this->talkLink()
789 . $sep . $this->historyLink()
790 . $sep . $this->whatLinksHere()
791 . $sep . $this->watchPageLinksLink();
793 if ( $wgTitle->getNamespace() == Namespace::getUser()
794 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
797 $id=User
::idFromName($wgTitle->getText());
798 $ip=User
::isIP($wgTitle->getText());
800 if($id ||
$ip) { # both anons and non-anons have contri list
801 $s .= $sep . $this->userContribsLink();
803 if ( 0 != $wgUser->getID() ) { # show only to signed in users
804 if($id) { # can only email non-anons
805 $s .= $sep . $this->emailUserLink();
809 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
810 $s .= "\n<br />" . $this->deleteThisPage() .
811 $sep . $this->protectThisPage() .
812 $sep . $this->moveThisPage();
814 $s .= "<br />\n" . $this->otherLanguages();
819 function pageStats() {
820 global $wgOut, $wgLang, $wgArticle, $wgRequest;
821 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
823 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
824 if ( ! $wgOut->isArticle() ) { return ''; }
825 if ( isset( $oldid ) ||
isset( $diff ) ) { return ''; }
826 if ( 0 == $wgArticle->getID() ) { return ''; }
829 if ( !$wgDisableCounters ) {
830 $count = $wgLang->formatNum( $wgArticle->getCount() );
832 $s = wfMsg( 'viewcount', $count );
836 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
837 require_once("Credits.php");
838 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
840 $s .= $this->lastModified();
843 return $s . ' ' . $this->getCopyright();
846 function getCopyright() {
847 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
850 $oldid = $wgRequest->getVal( 'oldid' );
851 $diff = $wgRequest->getVal( 'diff' );
853 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
854 $msg = 'history_copyright';
860 if( $wgRightsPage ) {
861 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
862 } elseif( $wgRightsUrl ) {
863 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
868 $out .= wfMsg( $msg, $link );
872 function getCopyrightIcon() {
873 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
875 if( $wgRightsIcon ) {
876 $icon = htmlspecialchars( $wgRightsIcon );
878 $url = htmlspecialchars( $wgRightsUrl );
879 $out .= '<a href="'.$url.'">';
881 $text = htmlspecialchars( $wgRightsText );
882 $out .= "<img src=\"$icon\" alt='$text' />";
890 function getPoweredBy() {
892 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
893 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
897 function lastModified() {
898 global $wgLang, $wgArticle;
900 $timestamp = $wgArticle->getTimestamp();
902 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
903 $s = ' ' . wfMsg( 'lastmodified', $d );
910 function logoText( $align = '' ) {
911 if ( '' != $align ) { $a = " align='{$align}'"; }
914 $mp = wfMsg( 'mainpage' );
915 $titleObj = Title
::newFromText( $mp );
916 if ( is_object( $titleObj ) ) {
917 $url = $titleObj->escapeLocalURL();
922 $logourl = $this->getLogo();
923 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
927 function quickBar() {
928 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
929 global $wgDisableUploads, $wgRemoteUploads;
931 $fname = 'Skin::quickBar';
932 wfProfileIn( $fname );
934 $action = $wgRequest->getText( 'action' );
935 $wpPreview = $wgRequest->getBool( 'wpPreview' );
936 $tns=$wgTitle->getNamespace();
938 $s = "\n<div id='quickbar'>";
939 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
942 $s .= $this->mainPageLink()
943 . $sep . $this->specialLink( 'recentchanges' )
944 . $sep . $this->specialLink( 'randompage' );
945 if ($wgUser->getID()) {
946 $s.= $sep . $this->specialLink( 'watchlist' ) ;
947 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
948 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
951 // only show watchlist link if logged in
952 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
953 $s .= "\n<br /><hr class='sep' />";
954 $articleExists = $wgTitle->getArticleId();
955 if ( $wgOut->isArticle() ||
$action =='edit' ||
$action =='history' ||
$wpPreview) {
956 if($wgOut->isArticle()) {
957 $s .= '<strong>' . $this->editThisPage() . '</strong>';
958 } else { # backlink to the article in edit or history mode
959 if($articleExists){ # no backlink if no article
962 $text = wfMsg('articlepage');
965 $text = wfMsg('viewtalkpage');
968 $text = wfMsg('userpage');
971 $text = wfMsg('viewtalkpage');
974 $text = wfMsg('wikipediapage');
977 $text = wfMsg('viewtalkpage');
980 $text = wfMsg('imagepage');
983 $text = wfMsg('viewtalkpage');
986 $text= wfMsg('articlepage');
989 $link = $wgTitle->getText();
990 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
991 $link = $nstext . ':' . $link ;
994 $s .= $this->makeLink( $link, $text );
995 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
996 # we just throw in a "New page" text to tell the user that he's in edit mode,
997 # and to avoid messing with the separator that is prepended to the next item
998 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
1004 if( $tns%2
&& $action!='edit' && !$wpPreview) {
1005 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit§ion=new');
1009 watching could cause problems in edit mode:
1010 if user edits article, then loads "watch this article" in background and then saves
1011 article with "Watch this article" checkbox disabled, the article is transparently
1012 unwatched. Therefore we do not show the "Watch this page" link in edit mode
1014 if ( 0 != $wgUser->getID() && $articleExists) {
1015 if($action!='edit' && $action != 'submit' )
1017 $s .= $sep . $this->watchThisPage();
1019 if ( $wgTitle->userCanEdit() )
1020 $s .= $sep . $this->moveThisPage();
1022 if ( $wgUser->isSysop() and $articleExists ) {
1023 $s .= $sep . $this->deleteThisPage() .
1024 $sep . $this->protectThisPage();
1026 $s .= $sep . $this->talkLink();
1027 if ($articleExists && $action !='history') {
1028 $s .= $sep . $this->historyLink();
1030 $s.=$sep . $this->whatLinksHere();
1032 if($wgOut->isArticleRelated()) {
1033 $s .= $sep . $this->watchPageLinksLink();
1036 if ( Namespace::getUser() == $wgTitle->getNamespace()
1037 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1040 $id=User
::idFromName($wgTitle->getText());
1041 $ip=User
::isIP($wgTitle->getText());
1044 $s .= $sep . $this->userContribsLink();
1046 if ( 0 != $wgUser->getID() ) {
1047 if($id) { # can only email real users
1048 $s .= $sep . $this->emailUserLink();
1052 $s .= "\n<br /><hr class='sep' />";
1055 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads ||
$wgRemoteUploads ) ) {
1056 $s .= $this->specialLink( 'upload' ) . $sep;
1058 $s .= $this->specialLink( 'specialpages' )
1059 . $sep . $this->bugReportsLink();
1061 global $wgSiteSupportPage;
1062 if( $wgSiteSupportPage ) {
1063 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1064 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1067 $s .= "\n<br /></div>\n";
1068 wfProfileOut( $fname );
1072 function specialPagesList() {
1073 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1074 require_once('SpecialPage.php');
1076 $pages = SpecialPage
::getPages();
1078 foreach ( $pages[''] as $name => $page ) {
1079 $a[$name] = $page->getDescription();
1081 if ( $wgUser->isSysop() )
1083 foreach ( $pages['sysop'] as $name => $page ) {
1084 $a[$name] = $page->getDescription();
1087 if ( $wgUser->isDeveloper() )
1089 foreach ( $pages['developer'] as $name => $page ) {
1090 $a[$name] = $page->getDescription() ;
1093 $go = wfMsg( 'go' );
1094 $sp = wfMsg( 'specialpages' );
1095 $spp = $wgLang->specialPage( 'Specialpages' );
1097 $s = '<form id="specialpages" method="get" class="inline" ' .
1098 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1099 $s .= "<select name=\"wpDropdown\">\n";
1100 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1102 foreach ( $a as $name => $desc ) {
1103 $p = $wgLang->specialPage( $name );
1104 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1106 $s .= "</select>\n";
1107 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1112 function mainPageLink() {
1113 $mp = wfMsg( 'mainpage' );
1114 $s = $this->makeKnownLink( $mp, $mp );
1118 function copyrightLink() {
1119 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1120 wfMsg( 'copyrightpagename' ) );
1124 function aboutLink() {
1125 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1126 wfMsg( 'aboutwikipedia' ) );
1131 function disclaimerLink() {
1132 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1133 wfMsg( 'disclaimers' ) );
1137 function editThisPage() {
1138 global $wgOut, $wgTitle, $wgRequest;
1140 $oldid = $wgRequest->getVal( 'oldid' );
1141 $diff = $wgRequest->getVal( 'diff' );
1142 $redirect = $wgRequest->getVal( 'redirect' );
1144 if ( ! $wgOut->isArticleRelated() ) {
1145 $s = wfMsg( 'protectedpage' );
1147 $n = $wgTitle->getPrefixedText();
1148 if ( $wgTitle->userCanEdit() ) {
1149 $t = wfMsg( 'editthispage' );
1151 #$t = wfMsg( "protectedpage" );
1152 $t = wfMsg( 'viewsource' );
1156 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1157 if ( $oldid && ! isset( $diff ) ) {
1158 $oid = '&oldid='.$oldid;
1160 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1165 function deleteThisPage() {
1166 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1168 $diff = $wgRequest->getVal( 'diff' );
1169 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1170 $n = $wgTitle->getPrefixedText();
1171 $t = wfMsg( 'deletethispage' );
1173 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1180 function protectThisPage() {
1181 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1183 $diff = $wgRequest->getVal( 'diff' );
1184 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1185 $n = $wgTitle->getPrefixedText();
1187 if ( $wgTitle->isProtected() ) {
1188 $t = wfMsg( 'unprotectthispage' );
1189 $q = 'action=unprotect';
1191 $t = wfMsg( 'protectthispage' );
1192 $q = 'action=protect';
1194 $s = $this->makeKnownLink( $n, $t, $q );
1201 function watchThisPage() {
1202 global $wgUser, $wgOut, $wgTitle;
1204 if ( $wgOut->isArticleRelated() ) {
1205 $n = $wgTitle->getPrefixedText();
1207 if ( $wgTitle->userIsWatching() ) {
1208 $t = wfMsg( 'unwatchthispage' );
1209 $q = 'action=unwatch';
1211 $t = wfMsg( 'watchthispage' );
1212 $q = 'action=watch';
1214 $s = $this->makeKnownLink( $n, $t, $q );
1216 $s = wfMsg( 'notanarticle' );
1221 function moveThisPage() {
1222 global $wgTitle, $wgLang;
1224 if ( $wgTitle->userCanEdit() ) {
1225 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1226 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1227 } // no message if page is protected - would be redundant
1231 function historyLink() {
1234 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1235 wfMsg( 'history' ), 'action=history' );
1239 function whatLinksHere() {
1240 global $wgTitle, $wgLang;
1242 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1243 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1247 function userContribsLink() {
1248 global $wgTitle, $wgLang;
1250 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1251 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1255 function emailUserLink() {
1256 global $wgTitle, $wgLang;
1258 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1259 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1263 function watchPageLinksLink() {
1264 global $wgOut, $wgTitle, $wgLang;
1266 if ( ! $wgOut->isArticleRelated() ) {
1267 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1269 $s = $this->makeKnownLink( $wgLang->specialPage(
1270 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1271 'target=' . $wgTitle->getPrefixedURL() );
1276 function otherLanguages() {
1277 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1279 $a = $wgOut->getLanguageLinks();
1280 if ( 0 == count( $a ) ) {
1281 if ( !$wgUseNewInterlanguage ) return '';
1282 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1283 if ( $ns != 0 AND $ns != 1 ) return '' ;
1285 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1286 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1287 wfMsg( 'intl' ) , $x );
1290 if ( !$wgUseNewInterlanguage ) {
1291 $s = wfMsg( 'otherlanguages' ) . ': ';
1293 global $wgLanguageCode ;
1294 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1295 $x .= '&xl='.$wgLanguageCode ;
1296 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1297 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1300 $s = wfMsg( 'otherlanguages' ) . ': ';
1302 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1303 foreach( $a as $l ) {
1304 if ( ! $first ) { $s .= ' | '; }
1307 $nt = Title
::newFromText( $l );
1308 $url = $nt->getFullURL();
1309 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1311 if ( '' == $text ) { $text = $l; }
1312 $style = $this->getExternalLinkAttributes( $l, $text );
1313 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1315 if($wgLang->isRTL()) $s .= '</span>';
1319 function bugReportsLink() {
1320 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1321 wfMsg( 'bugreports' ) );
1325 function dateLink() {
1326 global $wgLinkCache;
1327 $t1 = Title
::newFromText( gmdate( 'F j' ) );
1328 $t2 = Title
::newFromText( gmdate( 'Y' ) );
1330 $wgLinkCache->suspend();
1331 $id = $t1->getArticleID();
1332 $wgLinkCache->resume();
1335 $s = $this->makeBrokenLink( $t1->getText() );
1337 $s = $this->makeKnownLink( $t1->getText() );
1341 $wgLinkCache->suspend();
1342 $id = $t2->getArticleID();
1343 $wgLinkCache->resume();
1346 $s .= $this->makeBrokenLink( $t2->getText() );
1348 $s .= $this->makeKnownLink( $t2->getText() );
1353 function talkLink() {
1354 global $wgLang, $wgTitle, $wgLinkCache;
1356 $tns = $wgTitle->getNamespace();
1357 if ( -1 == $tns ) { return ''; }
1359 $pn = $wgTitle->getText();
1360 $tp = wfMsg( 'talkpage' );
1361 if ( Namespace::isTalk( $tns ) ) {
1362 $lns = Namespace::getSubject( $tns );
1365 $text = wfMsg('articlepage');
1368 $text = wfMsg('userpage');
1371 $text = wfMsg('wikipediapage');
1374 $text = wfMsg('imagepage');
1377 $text= wfMsg('articlepage');
1381 $lns = Namespace::getTalk( $tns );
1384 $n = $wgLang->getNsText( $lns );
1385 if ( '' == $n ) { $link = $pn; }
1386 else { $link = $n.':'.$pn; }
1388 $wgLinkCache->suspend();
1389 $s = $this->makeLink( $link, $text );
1390 $wgLinkCache->resume();
1395 function commentLink() {
1396 global $wgLang, $wgTitle, $wgLinkCache;
1398 $tns = $wgTitle->getNamespace();
1399 if ( -1 == $tns ) { return ''; }
1401 $lns = ( Namespace::isTalk( $tns ) ) ?
$tns : Namespace::getTalk( $tns );
1403 # assert Namespace::isTalk( $lns )
1405 $n = $wgLang->getNsText( $lns );
1406 $pn = $wgTitle->getText();
1410 $wgLinkCache->suspend();
1411 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit§ion=new');
1412 $wgLinkCache->resume();
1417 # After all the page content is transformed into HTML, it makes
1418 # a final pass through here for things like table backgrounds.
1420 function transformContent( $text ) {
1424 # Note: This function MUST call getArticleID() on the link,
1425 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1427 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1428 wfProfileIn( 'Skin::makeLink' );
1429 $nt = Title
::newFromText( $title );
1431 $result = $this->makeLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1433 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1434 $result = $text == "" ?
$title : $text;
1437 wfProfileOut( 'Skin::makeLink' );
1441 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1442 $nt = Title
::newFromText( $title );
1444 return $this->makeKnownLinkObj( Title
::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1446 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1447 return $text == '' ?
$title : $text;
1451 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1452 $nt = Title
::newFromText( $title );
1454 return $this->makeBrokenLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1456 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1457 return $text == '' ?
$title : $text;
1461 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1462 $nt = Title
::newFromText( $title );
1464 return $this->makeStubLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1466 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1467 return $text == '' ?
$title : $text;
1471 # Pass a title object, not a title string
1472 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' ) {
1473 global $wgOut, $wgUser;
1474 $fname = 'Skin::makeLinkObj';
1478 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1480 if ( $nt->isExternal() ) {
1481 $u = $nt->getFullURL();
1482 $link = $nt->getPrefixedURL();
1483 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1484 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1487 if ( '' != $trail ) {
1488 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1493 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1494 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1495 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1496 } elseif ( ( -1 == $nt->getNamespace() ) ||
1497 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1498 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1500 if ( $this->postParseLinkColour() ) {
1502 if ( '' != $trail ) {
1503 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1509 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1510 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1511 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1513 # Work out link colour immediately
1514 $aid = $nt->getArticleID() ;
1516 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1518 $threshold = $wgUser->getOption('stubthreshold') ;
1519 if ( $threshold > 0 ) {
1520 $dbr =& wfGetDB( DB_SLAVE
);
1521 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1522 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1523 if ( $s !== false ) {
1525 if ( $s->cur_is_redirect
OR $s->cur_namespace
!= 0 ) {
1526 $size = $threshold*2 ; # Really big
1528 $dbr->freeResult( $res );
1530 $size = $threshold*2 ; # Really big
1535 if ( $size < $threshold ) {
1536 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1538 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1546 # Pass a title object, not a title string
1547 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '' ) {
1548 global $wgOut, $wgTitle, $wgInputEncoding;
1550 $fname = 'Skin::makeKnownLinkObj';
1551 wfProfileIn( $fname );
1553 if ( !is_object( $nt ) ) {
1556 $link = $nt->getPrefixedURL();
1557 # if ( '' != $section && substr($section,0,1) != "#" ) {
1560 if ( '' == $link ) {
1562 if ( '' == $text ) {
1563 $text = htmlspecialchars( $nt->getFragment() );
1566 $u = $nt->escapeLocalURL( $query );
1568 if ( '' != $nt->getFragment() ) {
1569 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1570 $replacearray = array(
1574 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1576 if ( '' == $text ) {
1577 $text = htmlspecialchars( $nt->getPrefixedText() );
1579 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1582 if ( '' != $trail ) {
1583 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1588 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1589 wfProfileOut( $fname );
1593 # Pass a title object, not a title string
1594 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1595 global $wgOut, $wgUser;
1599 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1601 $fname = 'Skin::makeBrokenLinkObj';
1602 wfProfileIn( $fname );
1604 if ( '' == $query ) {
1607 $q = 'action=edit&'.$query;
1609 $u = $nt->escapeLocalURL( $q );
1611 if ( '' == $text ) {
1612 $text = htmlspecialchars( $nt->getPrefixedText() );
1614 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1617 if ( '' != $trail ) {
1618 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1623 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1624 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1626 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1629 wfProfileOut( $fname );
1633 # Pass a title object, not a title string
1634 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1635 global $wgOut, $wgUser;
1637 $link = $nt->getPrefixedURL();
1639 $u = $nt->escapeLocalURL( $query );
1641 if ( '' == $text ) {
1642 $text = htmlspecialchars( $nt->getPrefixedText() );
1644 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1647 if ( '' != $trail ) {
1648 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1653 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1654 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1656 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1661 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1662 $u = $nt->escapeLocalURL( $query );
1663 if ( '' == $text ) {
1664 $text = htmlspecialchars( $nt->getPrefixedText() );
1667 if ( '' != $trail ) {
1668 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1673 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1676 /* these are used extensively in SkinPHPTal, but also some other places */
1677 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1678 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1679 $this->checkTitle($title, $name);
1680 return $title->getLocalURL( $urlaction );
1682 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1683 $title = Title
::newFromText( $name );
1684 $title = $title->getTalkPage();
1685 $this->checkTitle($title, $name);
1686 return $title->getLocalURL( $urlaction );
1688 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1689 $title = Title
::newFromText( $name );
1690 $title= $title->getSubjectPage();
1691 $this->checkTitle($title, $name);
1692 return $title->getLocalURL( $urlaction );
1694 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1695 $title = Title
::newFromText( wfMsg($name) );
1696 $this->checkTitle($title, $name);
1697 return $title->getLocalURL( $urlaction );
1699 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1700 $title = Title
::newFromText( $name );
1701 $this->checkTitle($title, $name);
1702 return $title->getLocalURL( $urlaction );
1704 # this can be passed the NS number as defined in Language.php
1705 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1706 $title = Title
::makeTitleSafe( $namespace, $name );
1707 $this->checkTitle($title, $name);
1708 return $title->getLocalURL( $urlaction );
1711 /* these return an array with the 'href' and boolean 'exists' */
1712 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1713 $title = Title
::newFromText( $name );
1714 $this->checkTitle($title, $name);
1716 'href' => $title->getLocalURL( $urlaction ),
1717 'exists' => $title->getArticleID() != 0?
true:false
1720 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1721 $title = Title
::newFromText( $name );
1722 $title = $title->getTalkPage();
1723 $this->checkTitle($title, $name);
1725 'href' => $title->getLocalURL( $urlaction ),
1726 'exists' => $title->getArticleID() != 0?
true:false
1729 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1730 $title = Title
::newFromText( $name );
1731 $title= $title->getSubjectPage();
1732 $this->checkTitle($title, $name);
1734 'href' => $title->getLocalURL( $urlaction ),
1735 'exists' => $title->getArticleID() != 0?
true:false
1738 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1739 $title = Title
::newFromText( wfMsg($name) );
1740 $this->checkTitle($title, $name);
1742 'href' => $title->getLocalURL( $urlaction ),
1743 'exists' => $title->getArticleID() != 0?
true:false
1747 # make sure we have some title to operate on
1748 /*static*/ function checkTitle ( &$title, &$name ) {
1749 if(!is_object($title)) {
1750 $title = Title
::newFromText( $name );
1751 if(!is_object($title)) {
1752 $title = Title
::newFromText( '--error: link target missing--' );
1757 function fnamePart( $url ) {
1758 $basename = strrchr( $url, '/' );
1759 if ( false === $basename ) {
1762 $basename = substr( $basename, 1 );
1764 return htmlspecialchars( $basename );
1767 function makeImage( $url, $alt = '' ) {
1771 $alt = $this->fnamePart( $url );
1773 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1777 function makeImageLink( $name, $url, $alt = '' ) {
1778 $nt = Title
::makeTitleSafe( NS_IMAGE
, $name );
1779 return $this->makeImageLinkObj( $nt, $alt );
1782 function makeImageLinkObj( $nt, $alt = '' ) {
1783 global $wgLang, $wgUseImageResize;
1784 $img = Image
::newFromTitle( $nt );
1785 $url = $img->getURL();
1788 $prefix = $postfix = '';
1790 if ( $wgUseImageResize ) {
1791 # Check if the alt text is of the form "options|alt text"
1793 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1794 # * left no resizing, just left align. label is used for alt= only
1795 # * right same, but right aligned
1796 # * none same, but not aligned
1797 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1798 # * center center the image
1799 # * framed Keep original image size, no magnify-button.
1801 $part = explode( '|', $alt);
1803 $mwThumb =& MagicWord
::get( MAG_IMG_THUMBNAIL
);
1804 $mwLeft =& MagicWord
::get( MAG_IMG_LEFT
);
1805 $mwRight =& MagicWord
::get( MAG_IMG_RIGHT
);
1806 $mwNone =& MagicWord
::get( MAG_IMG_NONE
);
1807 $mwWidth =& MagicWord
::get( MAG_IMG_WIDTH
);
1808 $mwCenter =& MagicWord
::get( MAG_IMG_CENTER
);
1809 $mwFramed =& MagicWord
::get( MAG_IMG_FRAMED
);
1810 $alt = $part[count($part)-1];
1812 $height = $framed = $thumb = false;
1813 $manual_thumb = "" ;
1815 foreach( $part as $key => $val ) {
1816 $val_parts = explode ( "=" , $val , 2 ) ;
1817 $left_part = array_shift ( $val_parts ) ;
1818 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1820 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1821 # use manually specified thumbnail
1823 $manual_thumb = array_shift ( $val_parts ) ;
1824 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1825 # remember to set an alignment, don't render immediately
1827 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1828 # remember to set an alignment, don't render immediately
1830 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1831 # remember to set an alignment, don't render immediately
1833 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1834 # remember to set an alignment, don't render immediately
1836 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1837 # $match is the image width in pixels
1838 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1839 $width = intval( $m[1] );
1840 $height = intval( $m[2] );
1842 $width = intval($match);
1844 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1848 if ( 'center' == $align )
1850 $prefix = '<span style="text-align: center">';
1851 $postfix = '</span>';
1855 if ( $thumb ||
$framed ) {
1857 # Create a thumbnail. Alignment depends on language
1858 # writing direction, # right aligned for left-to-right-
1859 # languages ("Western languages"), left-aligned
1860 # for right-to-left-languages ("Semitic languages")
1862 # If thumbnail width has not been provided, it is set
1863 # here to 180 pixels
1864 if ( $align == '' ) {
1865 $align = $wgLang->isRTL() ?
'left' : 'right';
1867 if ( ! isset($width) ) {
1870 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1872 } elseif ( isset($width) ) {
1874 # Create a resized image, without the additional thumbnail
1877 if ( ( ! $height === false )
1878 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1879 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1880 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1881 $width = $img->getWidth() * $height / $img->getHeight();
1883 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1885 } # endif $wgUseImageResize
1887 if ( empty( $alt ) ) {
1888 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1890 $alt = htmlspecialchars( $alt );
1892 $u = $nt->escapeLocalURL();
1895 $s = wfMsg( 'missingimage', $img->getName() );
1896 $s .= "<br>{$alt}<br>{$url}<br>\n";
1898 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1899 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1901 if ( '' != $align ) {
1902 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1904 return str_replace("\n", ' ',$prefix.$s.$postfix);
1907 # Make HTML for a thumbnail including image, border and caption
1908 # $img is an Image object
1909 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1910 global $wgStylePath, $wgLang;
1911 # $image = Title::makeTitleSafe( NS_IMAGE, $name );
1912 $url = $img->getURL();
1914 #$label = htmlspecialchars( $label );
1915 $alt = preg_replace( '/<[^>]*>/', '', $label);
1916 $alt = htmlspecialchars( $alt );
1918 $width = $height = 0;
1919 if ( $img->exists() )
1921 $width = $img->getWidth();
1922 $height = $img->getHeight();
1924 if ( 0 == $width ||
0 == $height )
1926 $width = $height = 200;
1928 if ( $boxwidth == 0 )
1934 // Use image dimensions, don't scale
1936 $oboxwidth = $boxwidth +
2;
1937 $boxheight = $height;
1940 $h = intval( $height/($width/$boxwidth) );
1941 $oboxwidth = $boxwidth +
2;
1942 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1944 $boxwidth *= $boxheight/$h;
1948 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1951 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1953 $manual_title = Title
::makeTitleSafe( NS_IMAGE
, $manual_thumb ); #new Title ( $manual_thumb ) ;
1954 $manual_img = Image
::newFromTitle( $manual_title );
1955 $thumbUrl = $manual_img->getURL();
1956 if ( $manual_img->exists() )
1958 $width = $manual_img->getWidth();
1959 $height = $manual_img->getHeight();
1960 $boxwidth = $width ;
1961 $boxheight = $height ;
1962 $oboxwidth = $boxwidth +
2 ;
1966 $u = $img->getEscapeLocalURL();
1968 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1969 $magnifyalign = $wgLang->isRTL() ?
'left' : 'right';
1970 $textalign = $wgLang->isRTL() ?
' style="text-align:right"' : '';
1972 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1973 if ( $thumbUrl == '' ) {
1974 $s .= wfMsg( 'missingimage', $img->getName() );
1977 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1978 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1979 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1983 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1984 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1985 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1986 'width="15" height="11" alt="'.$more.'" /></a></div>';
1989 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1990 return str_replace("\n", ' ', $s);
1993 function makeMediaLink( $name, $url, $alt = '' ) {
1994 $nt = Title
::makeTitleSafe( Namespace::getMedia(), $name );
1995 return $this->makeMediaLinkObj( $nt, $alt );
1998 function makeMediaLinkObj( $nt, $alt = '' ) {
1999 if ( ! isset( $nt ) )
2001 ### HOTFIX. Instead of breaking, return empty string.
2004 $name = $nt->getDBKey();
2005 $url = Image
::wfImageUrl( $name );
2006 if ( empty( $alt ) ) {
2007 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2010 $u = htmlspecialchars( $url );
2011 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2016 function specialLink( $name, $key = '' ) {
2019 if ( '' == $key ) { $key = strtolower( $name ); }
2020 $pn = $wgLang->ucfirst( $name );
2021 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2025 function makeExternalLink( $url, $text, $escape = true ) {
2026 $style = $this->getExternalLinkAttributes( $url, $text );
2027 $url = htmlspecialchars( $url );
2029 $text = htmlspecialchars( $text );
2031 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2034 # Called by history lists and recent changes
2037 # Returns text for the start of the tabular part of RC
2038 function beginRecentChangesList() {
2039 $this->rc_cache
= array() ;
2040 $this->rcMoveIndex
= 0;
2041 $this->rcCacheIndex
= 0 ;
2042 $this->lastdate
= '';
2043 $this->rclistOpen
= false;
2047 function beginImageHistoryList() {
2048 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2049 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2053 # Returns text for the end of RC
2054 # If enhanced RC is in use, returns pretty much all the text
2055 function endRecentChangesList() {
2056 $s = $this->recentChangesBlock() ;
2057 if( $this->rclistOpen
) {
2063 # Enhanced RC ungrouped line
2064 function recentChangesBlockLine ( $rcObj ) {
2065 global $wgStylePath, $wgLang ;
2067 # Get rc_xxxx variables
2068 extract( $rcObj->mAttribs
) ;
2069 $curIdEq = 'curid='.$rc_cur_id;
2074 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2077 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2078 $r .= ' ';
2080 # M & N (minor & new)
2081 $M = wfMsg( 'minoreditletter' );
2082 $N = wfMsg( 'newpageletter' );
2084 if ( $rc_type == RC_NEW
) {
2097 $r .= ' '.$rcObj->timestamp
.' ' ;
2101 $link = $rcObj->link
;
2102 if ( $rcObj->watched
) $link = '<strong>'.$link.'</strong>' ;
2107 $r .= $rcObj->difflink
;
2111 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2114 $r .= ') . . '.$rcObj->userlink
;
2115 $r .= $rcObj->usertalklink
;
2118 if ( $rc_comment != '' && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2119 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2120 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2128 function recentChangesBlockGroup ( $block ) {
2129 global $wgStylePath, $wgLang ;
2132 $M = wfMsg( 'minoreditletter' );
2133 $N = wfMsg( 'newpageletter' );
2135 # Collate list of users
2137 $userlinks = array () ;
2138 foreach ( $block AS $rcObj ) {
2139 $oldid = $rcObj->mAttribs
['rc_last_oldid'];
2140 if ( $rcObj->mAttribs
['rc_new'] ) $isnew = true ;
2141 $u = $rcObj->userlink
;
2142 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2146 # Sort the list and convert to text
2147 krsort ( $userlinks ) ;
2148 asort ( $userlinks ) ;
2150 foreach ( $userlinks as $userlink => $count) {
2152 if ( $count > 1 ) $text .= " ({$count}×)" ;
2153 array_push ( $users , $text ) ;
2155 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2158 $rci = 'RCI'.$this->rcCacheIndex
;
2159 $rcl = 'RCL'.$this->rcCacheIndex
;
2160 $rcm = 'RCM'.$this->rcCacheIndex
;
2161 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2162 $arrowdir = $wgLang->isRTL() ?
'l' : 'r';
2163 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2164 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2170 if ( $isnew ) $r .= $N ;
2171 else $r .= ' ' ;
2172 $r .= ' ' ; # Minor
2175 $r .= ' '.$block[0]->timestamp
.' ' ;
2179 $link = $block[0]->link
;
2180 if ( $block[0]->watched
) $link = '<strong>'.$link.'</strong>' ;
2183 $curIdEq = 'curid=' . $block[0]->mAttribs
['rc_cur_id'];
2184 if ( $block[0]->mAttribs
['rc_type'] != RC_LOG
) {
2186 $r .= ' ('.count($block).' ' ;
2187 if ( $isnew ) $r .= wfMsg('changes');
2188 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2189 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2193 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2201 $r .= '<div id="'.$rci.'" style="display:none">' ;
2202 foreach ( $block AS $rcObj ) {
2203 # Get rc_xxxx variables
2204 extract( $rcObj->mAttribs
);
2206 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2207 $r .= '<tt> ' ;
2208 if ( $rc_new ) $r .= $N ;
2209 else $r .= ' ' ;
2210 if ( $rc_minor ) $r .= $M ;
2211 else $r .= ' ' ;
2215 if ( $rc_last_oldid != 0 ) {
2216 $o = 'oldid='.$rc_last_oldid ;
2218 if ( $rc_type == RC_LOG
) {
2219 $link = $rcObj->timestamp
;
2221 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp
, "{$curIdEq}&$o" ) ;
2223 $link = '<tt>'.$link.'</tt>' ;
2227 $r .= $rcObj->curlink
;
2229 $r .= $rcObj->lastlink
;
2230 $r .= ') . . '.$rcObj->userlink
;
2231 $r .= $rcObj->usertalklink
;
2232 if ( $rc_comment != '' ) {
2233 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2234 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2240 $this->rcCacheIndex++
;
2244 # If enhanced RC is in use, this function takes the previously cached
2245 # RC lines, arranges them, and outputs the HTML
2246 function recentChangesBlock () {
2247 global $wgStylePath ;
2248 if ( count ( $this->rc_cache
) == 0 ) return '' ;
2250 foreach ( $this->rc_cache
AS $secureName => $block ) {
2251 if ( count ( $block ) < 2 ) {
2252 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2254 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2258 return '<div>'.$blockOut.'</div>' ;
2261 # Called in a loop over all displayed RC entries
2262 # Either returns the line, or caches it for later use
2263 function recentChangesLine( &$rc, $watched = false ) {
2265 $usenew = $wgUser->getOption( 'usenewrc' );
2267 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2269 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2273 function recentChangesLineOld( &$rc, $watched = false ) {
2274 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2276 # Extract DB fields into local scope
2277 extract( $rc->mAttribs
);
2278 $curIdEq = 'curid=' . $rc_cur_id;
2280 # Make date header if necessary
2281 $date = $wgLang->date( $rc_timestamp, true);
2283 if ( $date != $this->lastdate
) {
2284 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2285 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2286 $this->lastdate
= $date;
2287 $this->rclistOpen
= true;
2290 # If this edit has not yet been patrolled, make it stick out
2291 $s .= ( ! $wgUseRCPatrol ||
$rc_patrolled ) ?
'<li> ' : '<li class="not_patrolled"> ';
2293 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2295 $s .= '(' . wfMsg( 'diff' ) . ') (';
2297 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2300 # "[[x]] moved to [[y]]"
2301 $msg = ( $rc_type == RC_MOVE
) ?
'1movedto2' : '1movedto2_redir';
2302 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2303 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2304 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2306 $logtype = $matches[1];
2307 $logname = LogPage
::logName( $logtype );
2308 $s .= '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2311 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2312 $diffLink = wfMsg( 'diff' );
2314 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2315 ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2316 $rcidparam = "&rcid={$rc_id}";
2319 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2320 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2321 '', '', ' tabindex="'.$rc->counter
.'"');
2323 $s .= '('.$diffLink.') (';
2326 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2329 # M and N (minor and new)
2330 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2331 if ( $rc_type == RC_NEW
) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2334 # If it's a new article, there is no diff link, but if it hasn't been
2335 # patrolled yet, we need to give users a way to do so
2336 if ( $wgUseRCPatrol && $rc_type == RC_NEW
&& $rc_patrolled == 0 &&
2337 $wgUser->getID() != 0 && ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2338 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2340 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2343 $articleLink = '<strong>'.$articleLink.'</strong>';
2345 $s .= ' '.$articleLink;
2350 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2352 # User link (or contributions for unregistered users)
2353 if ( 0 == $rc_user ) {
2354 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2355 $rc_user_text, 'target=' . $rc_user_text );
2357 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2362 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2363 global $wgDisableAnonTalk;
2364 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2367 $utns=$wgLang->getNsText(NS_USER_TALK
);
2368 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2372 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2373 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2374 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2378 if($userTalkLink) $userTalkLink .= ' | ';
2379 $userTalkLink .= $blockLink;
2381 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2384 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2385 $rc_comment=$this->formatComment($rc_comment,$rc->getTitle());
2386 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2393 function recentChangesLineNew( &$baseRC, $watched = false ) {
2394 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2396 # Create a specialised object
2397 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2399 # Extract fields from DB into the function scope (rc_xxxx variables)
2400 extract( $rc->mAttribs
);
2401 $curIdEq = 'curid=' . $rc_cur_id;
2403 # If it's a new day, add the headline and flush the cache
2404 $date = $wgLang->date( $rc_timestamp, true);
2406 if ( $date != $this->lastdate
) {
2407 # Process current cache
2408 $ret = $this->recentChangesBlock () ;
2409 $this->rc_cache
= array() ;
2410 $ret .= "<h4>{$date}</h4>\n";
2411 $this->lastdate
= $date;
2415 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2416 $msg = ( $rc_type == RC_MOVE
) ?
"1movedto2" : "1movedto2_redir";
2417 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2418 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2419 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2421 $logtype = $matches[1];
2422 $logname = LogPage
::logName( $logtype );
2423 $clink = '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2425 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2428 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2429 $rc->watched
= $watched ;
2430 $rc->link
= $clink ;
2431 $rc->timestamp
= $time;
2433 # Make "cur" and "diff" links
2434 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2435 $curLink = wfMsg( 'cur' );
2436 $diffLink = wfMsg( 'diff' );
2438 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2439 $aprops = ' tabindex="'.$baseRC->counter
.'"';
2440 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2441 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2445 $titleObj = $rc->getTitle();
2446 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2447 $lastLink = wfMsg( 'last' );
2449 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2450 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2453 # Make user link (or user contributions for unregistered users)
2454 if ( $rc_user == 0 ) {
2455 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2456 $rc_user_text, 'target=' . $rc_user_text );
2458 $userLink = $this->makeLink( $wgLang->getNsText(
2459 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2462 $rc->userlink
= $userLink;
2463 $rc->lastlink
= $lastLink;
2464 $rc->curlink
= $curLink;
2465 $rc->difflink
= $diffLink;
2467 # Make user talk link
2468 $utns=$wgLang->getNsText(NS_USER_TALK
);
2469 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2470 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2472 global $wgDisableAnonTalk;
2473 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2474 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2475 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2476 if( $wgDisableAnonTalk )
2477 $rc->usertalklink
= ' ('.$blockLink.')';
2479 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2481 if( $wgDisableAnonTalk && ($rc_user == 0) )
2482 $rc->usertalklink
= '';
2484 $rc->usertalklink
= ' ('.$userTalkLink.')';
2487 # Put accumulated information into the cache, for later display
2488 # Page moves go on their own line
2489 $title = $rc->getTitle();
2490 $secureName = $title->getPrefixedDBkey();
2491 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2492 # Use an @ character to prevent collision with page names
2493 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2495 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2496 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2501 function endImageHistoryList() {
2506 /* This function is called by all recent changes variants, by the page history,
2507 and by the user contributions list. It is responsible for formatting edit
2508 comments. It escapes any HTML in the comment, but adds some CSS to format
2509 auto-generated comments (from section editing) and formats [[wikilinks]].
2511 The &$title parameter must be a title OBJECT. It is used to generate a
2512 direct link to the section in the autocomment.
2513 Main author: Erik Moeller (moeller@scireview.de)
2515 # Note: there's not always a title to pass to this function.
2516 # Since you can't set a default parameter for a reference, I've turned it
2517 # temporarily to a value pass. Should be adjusted further. --brion
2518 function formatComment($comment, $title = NULL) {
2520 $comment = htmlspecialchars( $comment );
2522 # The pattern for autogen comments is / * foo * /, which makes for
2524 # We look for all comments, match any text before and after the comment,
2525 # add a separator where needed and format the comment itself with CSS
2526 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2534 # This is hackish but should work in most cases.
2535 $section=str_replace('[[','',$section);
2536 $section=str_replace(']]','',$section);
2537 $title->mFragment
=$section;
2538 $link=$this->makeKnownLinkObj($title,wfMsg('sectionlink'));
2542 if($pre) { $auto = $sep.' '.$auto; }
2543 if($post) { $auto .= ' '.$sep; }
2544 $auto='<span class="autocomment">'.$auto.'</span>';
2545 $comment=$pre.$auto.$post;
2548 # format regular and media links - all other wiki formatting
2550 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2551 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2552 # Handle link renaming [[foo|text]] will show link as "text"
2553 if( "" != $match[3] ) {
2558 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2559 # Media link; trail not supported.
2560 $linkRegexp = '/\[\[(.*?)\]\]/';
2561 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2563 # Other kind of link
2564 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2565 $trail = $submatch[1];
2569 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2570 if ($match[1][0] == ':')
2571 $match[1] = substr($match[1], 1);
2572 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2574 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2579 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description ) {
2580 global $wgUser, $wgLang, $wgTitle;
2582 $datetime = $wgLang->timeanddate( $timestamp, true );
2583 $del = wfMsg( 'deleteimg' );
2584 $delall = wfMsg( 'deleteimgcompletely' );
2585 $cur = wfMsg( 'cur' );
2588 $url = Image
::wfImageUrl( $img );
2590 if ( $wgUser->isSysop() ) {
2591 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2593 $style = $this->getInternalLinkAttributes( $link, $delall );
2595 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2600 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2601 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2602 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2603 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2604 urlencode( $img ) );
2605 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2606 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2608 # Having live active links for non-logged in users
2609 # means that bots and spiders crawling our site can
2610 # inadvertently change content. Baaaad idea.
2611 $rlink = wfMsg( 'revertimg' );
2616 $userlink = $usertext;
2618 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2619 ':'.$usertext, $usertext );
2621 $nbytes = wfMsg( 'nbytes', $size );
2622 $style = $this->getInternalLinkAttributes( $url, $datetime );
2624 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2625 . " . . {$userlink} ({$nbytes})";
2627 if ( '' != $description && '*' != $description ) {
2628 $sk=$wgUser->getSkin();
2629 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description,$wgTitle) . ')');
2635 function tocIndent($level) {
2636 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2639 function tocUnindent($level) {
2640 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2643 # parameter level defines if we are on an indentation level
2644 function tocLine( $anchor, $tocline, $level ) {
2645 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2649 return '<div class="tocline">'.$link."</div>\n";
2654 function tocTable($toc) {
2655 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2656 # try min-width & co when somebody gets a chance
2657 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2659 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2660 '<b>'.wfMsg('toc').'</b>' .
2662 '</td></tr><tr id="tocinside"><td>'."\n".
2663 $toc."</td></tr></table>\n";
2666 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2667 function editSectionScript( $section, $head ) {
2668 global $wgTitle, $wgRequest;
2669 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2672 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2673 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2676 function editSectionLink( $section ) {
2678 global $wgTitle, $wgUser, $wgLang;
2680 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2681 # Section edit links would be out of sync on an old page.
2682 # But, if we're diffing to the current page, they'll be
2687 $editurl = '§ion='.$section;
2688 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2690 if( $wgLang->isRTL() ) {
2692 $nearside = 'right';
2697 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2701 // This function is called by EditPage.php and shows a bulletin board style
2702 // toolbar for common editing functions. It can be disabled in the user preferences.
2703 // The necsesary JavaScript code can be found in style/wikibits.js.
2704 function getEditToolbar() {
2705 global $wgStylePath, $wgLang, $wgMimeType;
2707 // toolarray an array of arrays which each include the filename of
2708 // the button image (without path), the opening tag, the closing tag,
2709 // and optionally a sample text that is inserted between the two when no
2710 // selection is highlighted.
2711 // The tip text is shown when the user moves the mouse over the button.
2713 // Already here are accesskeys (key), which are not used yet until someone
2714 // can figure out a way to make them work in IE. However, we should make
2715 // sure these keys are not defined on the edit page.
2717 array( 'image'=>'button_bold.png',
2719 'close' => "\'\'\'",
2720 'sample'=> wfMsg('bold_sample'),
2721 'tip' => wfMsg('bold_tip'),
2724 array( 'image'=>'button_italic.png',
2727 'sample'=> wfMsg('italic_sample'),
2728 'tip' => wfMsg('italic_tip'),
2731 array( 'image'=>'button_link.png',
2734 'sample'=> wfMsg('link_sample'),
2735 'tip' => wfMsg('link_tip'),
2738 array( 'image'=>'button_extlink.png',
2741 'sample'=> wfMsg('extlink_sample'),
2742 'tip' => wfMsg('extlink_tip'),
2745 array( 'image'=>'button_headline.png',
2747 'close' => " ==\\n",
2748 'sample'=> wfMsg('headline_sample'),
2749 'tip' => wfMsg('headline_tip'),
2752 array( 'image'=>'button_image.png',
2753 'open' => '[['.$wgLang->getNsText(NS_IMAGE
).":",
2755 'sample'=> wfMsg('image_sample'),
2756 'tip' => wfMsg('image_tip'),
2759 array( 'image' => 'button_media.png',
2760 'open' => '[['.$wgLang->getNsText(NS_MEDIA
).':',
2762 'sample'=> wfMsg('media_sample'),
2763 'tip' => wfMsg('media_tip'),
2766 array( 'image' => 'button_math.png',
2767 'open' => "\\<math\\>",
2768 'close' => "\\</math\\>",
2769 'sample'=> wfMsg('math_sample'),
2770 'tip' => wfMsg('math_tip'),
2773 array( 'image' => 'button_nowiki.png',
2774 'open' => "\\<nowiki\\>",
2775 'close' => "\\</nowiki\\>",
2776 'sample'=> wfMsg('nowiki_sample'),
2777 'tip' => wfMsg('nowiki_tip'),
2780 array( 'image' => 'button_sig.png',
2784 'tip' => wfMsg('sig_tip'),
2787 array( 'image' => 'button_hr.png',
2788 'open' => "\\n----\\n",
2791 'tip' => wfMsg('hr_tip'),
2795 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2797 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2798 foreach($toolarray as $tool) {
2800 $image=$wgStylePath.'/images/'.$tool['image'];
2801 $open=$tool['open'];
2802 $close=$tool['close'];
2803 $sample = addslashes( $tool['sample'] );
2805 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2806 // Older browsers show a "speedtip" type message only for ALT.
2807 // Ideally these should be different, realistically they
2808 // probably don't need to be.
2809 $tip = addslashes( $tool['tip'] );
2811 #$key = $tool["key"];
2813 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2816 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2817 $toolbar.="document.writeln(\"</div>\");\n";
2819 $toolbar.="/*]]>*/\n</script>";
2823 /* public */ function suppressUrlExpansion() {