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>';
595 $undelete = $this->getUndeleteLink();
596 if( !empty( $undelete ) ) {
597 $s .= ' | '.$undelete;
602 function getUndeleteLink() {
603 global $wgUser, $wgTitle, $wgLang, $action;
604 if( $wgUser->isSysop() &&
605 (($wgTitle->getArticleId() == 0) ||
($action == "history")) &&
606 ($n = $wgTitle->isDeleted() ) ) {
607 return wfMsg( 'thisisdeleted',
608 $this->makeKnownLink(
609 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
610 wfMsg( 'restorelink', $n ) ) );
615 function printableLink() {
616 global $wgOut, $wgFeedClasses, $wgRequest;
618 $baseurl = $_SERVER['REQUEST_URI'];
619 if( strpos( '?', $baseurl ) == false ) {
624 $baseurl = htmlspecialchars( $baseurl );
625 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
627 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
628 if( $wgOut->isSyndicated() ) {
629 foreach( $wgFeedClasses as $format => $class ) {
630 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
631 $s .= " | <a href=\"$feedurl\">{$format}</a>";
637 function pageTitle() {
638 global $wgOut, $wgTitle, $wgUser;
640 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
641 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
645 function pageSubtitle() {
648 $sub = $wgOut->getSubtitle();
650 global $wgExtraSubtitle;
651 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
653 $subpages = $this->subPageSubtitle();
654 $sub .= !empty($subpages)?
"</p><p class='subpages'>$subpages":'';
655 $s = "<p class='subtitle'>{$sub}</p>\n";
659 function subPageSubtitle() {
660 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
662 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
663 $ptext=$wgTitle->getPrefixedText();
664 if(preg_match('/\//',$ptext)) {
665 $links = explode('/',$ptext);
668 foreach($links as $link) {
670 if ($c<count($links)) {
671 $growinglink .= $link;
672 $getlink = $this->makeLink( $growinglink, $link );
673 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
677 $subpages .= '< ';
679 $subpages .= $getlink;
688 function nameAndLogin() {
689 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
691 $li = $wgLang->specialPage( 'Userlogin' );
692 $lo = $wgLang->specialPage( 'Userlogout' );
695 if ( 0 == $wgUser->getID() ) {
696 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
699 $tl = $this->makeKnownLink( $wgLang->getNsText(
700 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
701 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
703 $s .= $n . ' ('.$tl.')';
705 $s .= wfMsg('notloggedin');
708 $rt = $wgTitle->getPrefixedURL();
709 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
711 } else { $q = "returnto={$rt}"; }
713 $s .= "\n<br />" . $this->makeKnownLink( $li,
714 wfMsg( 'login' ), $q );
716 $n = $wgUser->getName();
717 $rt = $wgTitle->getPrefixedURL();
718 $tl = $this->makeKnownLink( $wgLang->getNsText(
719 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
720 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
724 $s .= $this->makeKnownLink( $wgLang->getNsText(
725 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
726 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
727 "returnto={$rt}" ) . ' | ' .
728 $this->specialLink( 'preferences' );
730 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
736 function getSearchLink() {
737 $searchPage =& Title
::makeTitle( NS_SPECIAL
, 'Search' );
738 return $searchPage->getLocalURL();
741 function escapeSearchLink() {
742 return htmlspecialchars( $this->getSearchLink() );
745 function searchForm() {
747 $search = $wgRequest->getText( 'search' );
749 $s = '<form name="search" class="inline" method="post" action="'
750 . $this->escapeSearchLink() . "\">\n"
751 . '<input type="text" name="search" size="19" value="'
752 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
753 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" /> '
754 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
759 function topLinks() {
763 $s = $this->mainPageLink() . $sep
764 . $this->specialLink( 'recentchanges' );
766 if ( $wgOut->isArticleRelated() ) {
767 $s .= $sep . $this->editThisPage()
768 . $sep . $this->historyLink();
770 # Many people don't like this dropdown box
771 #$s .= $sep . $this->specialPagesList();
776 function bottomLinks() {
777 global $wgOut, $wgUser, $wgTitle;
781 if ( $wgOut->isArticleRelated() ) {
782 $s .= '<strong>' . $this->editThisPage() . '</strong>';
783 if ( 0 != $wgUser->getID() ) {
784 $s .= $sep . $this->watchThisPage();
786 $s .= $sep . $this->talkLink()
787 . $sep . $this->historyLink()
788 . $sep . $this->whatLinksHere()
789 . $sep . $this->watchPageLinksLink();
791 if ( $wgTitle->getNamespace() == Namespace::getUser()
792 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
795 $id=User
::idFromName($wgTitle->getText());
796 $ip=User
::isIP($wgTitle->getText());
798 if($id ||
$ip) { # both anons and non-anons have contri list
799 $s .= $sep . $this->userContribsLink();
801 if ( 0 != $wgUser->getID() ) { # show only to signed in users
802 if($id) { # can only email non-anons
803 $s .= $sep . $this->emailUserLink();
807 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
808 $s .= "\n<br />" . $this->deleteThisPage() .
809 $sep . $this->protectThisPage() .
810 $sep . $this->moveThisPage();
812 $s .= "<br />\n" . $this->otherLanguages();
817 function pageStats() {
818 global $wgOut, $wgLang, $wgArticle, $wgRequest;
819 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
821 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
822 if ( ! $wgOut->isArticle() ) { return ''; }
823 if ( isset( $oldid ) ||
isset( $diff ) ) { return ''; }
824 if ( 0 == $wgArticle->getID() ) { return ''; }
827 if ( !$wgDisableCounters ) {
828 $count = $wgLang->formatNum( $wgArticle->getCount() );
830 $s = wfMsg( 'viewcount', $count );
834 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
835 require_once("Credits.php");
836 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
838 $s .= $this->lastModified();
841 return $s . ' ' . $this->getCopyright();
844 function getCopyright() {
845 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
848 $oldid = $wgRequest->getVal( 'oldid' );
849 $diff = $wgRequest->getVal( 'diff' );
851 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
852 $msg = 'history_copyright';
858 if( $wgRightsPage ) {
859 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
860 } elseif( $wgRightsUrl ) {
861 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
866 $out .= wfMsg( $msg, $link );
870 function getCopyrightIcon() {
871 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
873 if( $wgRightsIcon ) {
874 $icon = htmlspecialchars( $wgRightsIcon );
876 $url = htmlspecialchars( $wgRightsUrl );
877 $out .= '<a href="'.$url.'">';
879 $text = htmlspecialchars( $wgRightsText );
880 $out .= "<img src=\"$icon\" alt='$text' />";
888 function getPoweredBy() {
890 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
891 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
895 function lastModified() {
896 global $wgLang, $wgArticle;
898 $timestamp = $wgArticle->getTimestamp();
900 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
901 $s = ' ' . wfMsg( 'lastmodified', $d );
908 function logoText( $align = '' ) {
909 if ( '' != $align ) { $a = " align='{$align}'"; }
912 $mp = wfMsg( 'mainpage' );
913 $titleObj = Title
::newFromText( $mp );
914 if ( is_object( $titleObj ) ) {
915 $url = $titleObj->escapeLocalURL();
920 $logourl = $this->getLogo();
921 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
925 function quickBar() {
926 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
927 global $wgDisableUploads, $wgRemoteUploads;
929 $fname = 'Skin::quickBar';
930 wfProfileIn( $fname );
932 $action = $wgRequest->getText( 'action' );
933 $wpPreview = $wgRequest->getBool( 'wpPreview' );
934 $tns=$wgTitle->getNamespace();
936 $s = "\n<div id='quickbar'>";
937 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
940 $s .= $this->mainPageLink()
941 . $sep . $this->specialLink( 'recentchanges' )
942 . $sep . $this->specialLink( 'randompage' );
943 if ($wgUser->getID()) {
944 $s.= $sep . $this->specialLink( 'watchlist' ) ;
945 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
946 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
949 // only show watchlist link if logged in
950 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
951 $s .= "\n<br /><hr class='sep' />";
952 $articleExists = $wgTitle->getArticleId();
953 if ( $wgOut->isArticle() ||
$action =='edit' ||
$action =='history' ||
$wpPreview) {
954 if($wgOut->isArticle()) {
955 $s .= '<strong>' . $this->editThisPage() . '</strong>';
956 } else { # backlink to the article in edit or history mode
957 if($articleExists){ # no backlink if no article
960 $text = wfMsg('articlepage');
963 $text = wfMsg('viewtalkpage');
966 $text = wfMsg('userpage');
969 $text = wfMsg('viewtalkpage');
972 $text = wfMsg('wikipediapage');
975 $text = wfMsg('viewtalkpage');
978 $text = wfMsg('imagepage');
981 $text = wfMsg('viewtalkpage');
984 $text= wfMsg('articlepage');
987 $link = $wgTitle->getText();
988 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
989 $link = $nstext . ':' . $link ;
992 $s .= $this->makeLink( $link, $text );
993 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
994 # we just throw in a "New page" text to tell the user that he's in edit mode,
995 # and to avoid messing with the separator that is prepended to the next item
996 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
1002 if( $tns%2
&& $action!='edit' && !$wpPreview) {
1003 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit§ion=new');
1007 watching could cause problems in edit mode:
1008 if user edits article, then loads "watch this article" in background and then saves
1009 article with "Watch this article" checkbox disabled, the article is transparently
1010 unwatched. Therefore we do not show the "Watch this page" link in edit mode
1012 if ( 0 != $wgUser->getID() && $articleExists) {
1013 if($action!='edit' && $action != 'submit' )
1015 $s .= $sep . $this->watchThisPage();
1017 if ( $wgTitle->userCanEdit() )
1018 $s .= $sep . $this->moveThisPage();
1020 if ( $wgUser->isSysop() and $articleExists ) {
1021 $s .= $sep . $this->deleteThisPage() .
1022 $sep . $this->protectThisPage();
1024 $s .= $sep . $this->talkLink();
1025 if ($articleExists && $action !='history') {
1026 $s .= $sep . $this->historyLink();
1028 $s.=$sep . $this->whatLinksHere();
1030 if($wgOut->isArticleRelated()) {
1031 $s .= $sep . $this->watchPageLinksLink();
1034 if ( Namespace::getUser() == $wgTitle->getNamespace()
1035 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1038 $id=User
::idFromName($wgTitle->getText());
1039 $ip=User
::isIP($wgTitle->getText());
1042 $s .= $sep . $this->userContribsLink();
1044 if ( 0 != $wgUser->getID() ) {
1045 if($id) { # can only email real users
1046 $s .= $sep . $this->emailUserLink();
1050 $s .= "\n<br /><hr class='sep' />";
1053 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads ||
$wgRemoteUploads ) ) {
1054 $s .= $this->specialLink( 'upload' ) . $sep;
1056 $s .= $this->specialLink( 'specialpages' )
1057 . $sep . $this->bugReportsLink();
1059 global $wgSiteSupportPage;
1060 if( $wgSiteSupportPage ) {
1061 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1062 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1065 $s .= "\n<br /></div>\n";
1066 wfProfileOut( $fname );
1070 function specialPagesList() {
1071 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1072 require_once('SpecialPage.php');
1074 $pages = SpecialPage
::getPages();
1076 foreach ( $pages[''] as $name => $page ) {
1077 $a[$name] = $page->getDescription();
1079 if ( $wgUser->isSysop() )
1081 foreach ( $pages['sysop'] as $name => $page ) {
1082 $a[$name] = $page->getDescription();
1085 if ( $wgUser->isDeveloper() )
1087 foreach ( $pages['developer'] as $name => $page ) {
1088 $a[$name] = $page->getDescription() ;
1091 $go = wfMsg( 'go' );
1092 $sp = wfMsg( 'specialpages' );
1093 $spp = $wgLang->specialPage( 'Specialpages' );
1095 $s = '<form id="specialpages" method="get" class="inline" ' .
1096 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1097 $s .= "<select name=\"wpDropdown\">\n";
1098 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1100 foreach ( $a as $name => $desc ) {
1101 $p = $wgLang->specialPage( $name );
1102 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1104 $s .= "</select>\n";
1105 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1110 function mainPageLink() {
1111 $mp = wfMsg( 'mainpage' );
1112 $s = $this->makeKnownLink( $mp, $mp );
1116 function copyrightLink() {
1117 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1118 wfMsg( 'copyrightpagename' ) );
1122 function aboutLink() {
1123 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1124 wfMsg( 'aboutwikipedia' ) );
1129 function disclaimerLink() {
1130 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1131 wfMsg( 'disclaimers' ) );
1135 function editThisPage() {
1136 global $wgOut, $wgTitle, $wgRequest;
1138 $oldid = $wgRequest->getVal( 'oldid' );
1139 $diff = $wgRequest->getVal( 'diff' );
1140 $redirect = $wgRequest->getVal( 'redirect' );
1142 if ( ! $wgOut->isArticleRelated() ) {
1143 $s = wfMsg( 'protectedpage' );
1145 $n = $wgTitle->getPrefixedText();
1146 if ( $wgTitle->userCanEdit() ) {
1147 $t = wfMsg( 'editthispage' );
1149 #$t = wfMsg( "protectedpage" );
1150 $t = wfMsg( 'viewsource' );
1154 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1155 if ( $oldid && ! isset( $diff ) ) {
1156 $oid = '&oldid='.$oldid;
1158 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1163 function deleteThisPage() {
1164 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1166 $diff = $wgRequest->getVal( 'diff' );
1167 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1168 $n = $wgTitle->getPrefixedText();
1169 $t = wfMsg( 'deletethispage' );
1171 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1178 function protectThisPage() {
1179 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1181 $diff = $wgRequest->getVal( 'diff' );
1182 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1183 $n = $wgTitle->getPrefixedText();
1185 if ( $wgTitle->isProtected() ) {
1186 $t = wfMsg( 'unprotectthispage' );
1187 $q = 'action=unprotect';
1189 $t = wfMsg( 'protectthispage' );
1190 $q = 'action=protect';
1192 $s = $this->makeKnownLink( $n, $t, $q );
1199 function watchThisPage() {
1200 global $wgUser, $wgOut, $wgTitle;
1202 if ( $wgOut->isArticleRelated() ) {
1203 $n = $wgTitle->getPrefixedText();
1205 if ( $wgTitle->userIsWatching() ) {
1206 $t = wfMsg( 'unwatchthispage' );
1207 $q = 'action=unwatch';
1209 $t = wfMsg( 'watchthispage' );
1210 $q = 'action=watch';
1212 $s = $this->makeKnownLink( $n, $t, $q );
1214 $s = wfMsg( 'notanarticle' );
1219 function moveThisPage() {
1220 global $wgTitle, $wgLang;
1222 if ( $wgTitle->userCanEdit() ) {
1223 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1224 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1225 } // no message if page is protected - would be redundant
1229 function historyLink() {
1232 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1233 wfMsg( 'history' ), 'action=history' );
1237 function whatLinksHere() {
1238 global $wgTitle, $wgLang;
1240 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1241 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1245 function userContribsLink() {
1246 global $wgTitle, $wgLang;
1248 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1249 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1253 function emailUserLink() {
1254 global $wgTitle, $wgLang;
1256 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1257 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1261 function watchPageLinksLink() {
1262 global $wgOut, $wgTitle, $wgLang;
1264 if ( ! $wgOut->isArticleRelated() ) {
1265 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1267 $s = $this->makeKnownLink( $wgLang->specialPage(
1268 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1269 'target=' . $wgTitle->getPrefixedURL() );
1274 function otherLanguages() {
1275 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1277 $a = $wgOut->getLanguageLinks();
1278 if ( 0 == count( $a ) ) {
1279 if ( !$wgUseNewInterlanguage ) return '';
1280 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1281 if ( $ns != 0 AND $ns != 1 ) return '' ;
1283 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1284 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1285 wfMsg( 'intl' ) , $x );
1288 if ( !$wgUseNewInterlanguage ) {
1289 $s = wfMsg( 'otherlanguages' ) . ': ';
1291 global $wgLanguageCode ;
1292 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1293 $x .= '&xl='.$wgLanguageCode ;
1294 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1295 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1298 $s = wfMsg( 'otherlanguages' ) . ': ';
1300 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1301 foreach( $a as $l ) {
1302 if ( ! $first ) { $s .= ' | '; }
1305 $nt = Title
::newFromText( $l );
1306 $url = $nt->getFullURL();
1307 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1309 if ( '' == $text ) { $text = $l; }
1310 $style = $this->getExternalLinkAttributes( $l, $text );
1311 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1313 if($wgLang->isRTL()) $s .= '</span>';
1317 function bugReportsLink() {
1318 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1319 wfMsg( 'bugreports' ) );
1323 function dateLink() {
1324 global $wgLinkCache;
1325 $t1 = Title
::newFromText( gmdate( 'F j' ) );
1326 $t2 = Title
::newFromText( gmdate( 'Y' ) );
1328 $wgLinkCache->suspend();
1329 $id = $t1->getArticleID();
1330 $wgLinkCache->resume();
1333 $s = $this->makeBrokenLink( $t1->getText() );
1335 $s = $this->makeKnownLink( $t1->getText() );
1339 $wgLinkCache->suspend();
1340 $id = $t2->getArticleID();
1341 $wgLinkCache->resume();
1344 $s .= $this->makeBrokenLink( $t2->getText() );
1346 $s .= $this->makeKnownLink( $t2->getText() );
1351 function talkLink() {
1352 global $wgLang, $wgTitle, $wgLinkCache;
1354 $tns = $wgTitle->getNamespace();
1355 if ( -1 == $tns ) { return ''; }
1357 $pn = $wgTitle->getText();
1358 $tp = wfMsg( 'talkpage' );
1359 if ( Namespace::isTalk( $tns ) ) {
1360 $lns = Namespace::getSubject( $tns );
1363 $text = wfMsg('articlepage');
1366 $text = wfMsg('userpage');
1369 $text = wfMsg('wikipediapage');
1372 $text = wfMsg('imagepage');
1375 $text= wfMsg('articlepage');
1379 $lns = Namespace::getTalk( $tns );
1382 $n = $wgLang->getNsText( $lns );
1383 if ( '' == $n ) { $link = $pn; }
1384 else { $link = $n.':'.$pn; }
1386 $wgLinkCache->suspend();
1387 $s = $this->makeLink( $link, $text );
1388 $wgLinkCache->resume();
1393 function commentLink() {
1394 global $wgLang, $wgTitle, $wgLinkCache;
1396 $tns = $wgTitle->getNamespace();
1397 if ( -1 == $tns ) { return ''; }
1399 $lns = ( Namespace::isTalk( $tns ) ) ?
$tns : Namespace::getTalk( $tns );
1401 # assert Namespace::isTalk( $lns )
1403 $n = $wgLang->getNsText( $lns );
1404 $pn = $wgTitle->getText();
1408 $wgLinkCache->suspend();
1409 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit§ion=new');
1410 $wgLinkCache->resume();
1415 # After all the page content is transformed into HTML, it makes
1416 # a final pass through here for things like table backgrounds.
1418 function transformContent( $text ) {
1422 # Note: This function MUST call getArticleID() on the link,
1423 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1425 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1426 wfProfileIn( 'Skin::makeLink' );
1427 $nt = Title
::newFromText( $title );
1429 $result = $this->makeLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1431 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1432 $result = $text == "" ?
$title : $text;
1435 wfProfileOut( 'Skin::makeLink' );
1439 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1440 $nt = Title
::newFromText( $title );
1442 return $this->makeKnownLinkObj( Title
::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1444 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1445 return $text == '' ?
$title : $text;
1449 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1450 $nt = Title
::newFromText( $title );
1452 return $this->makeBrokenLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1454 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1455 return $text == '' ?
$title : $text;
1459 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1460 $nt = Title
::newFromText( $title );
1462 return $this->makeStubLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1464 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1465 return $text == '' ?
$title : $text;
1469 # Pass a title object, not a title string
1470 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' ) {
1471 global $wgOut, $wgUser;
1472 $fname = 'Skin::makeLinkObj';
1476 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1478 if ( $nt->isExternal() ) {
1479 $u = $nt->getFullURL();
1480 $link = $nt->getPrefixedURL();
1481 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1482 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1485 if ( '' != $trail ) {
1486 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1491 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1492 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1493 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1494 } elseif ( ( -1 == $nt->getNamespace() ) ||
1495 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1496 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1498 if ( $this->postParseLinkColour() ) {
1500 if ( '' != $trail ) {
1501 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1507 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1508 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1509 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1511 # Work out link colour immediately
1512 $aid = $nt->getArticleID() ;
1514 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1516 $threshold = $wgUser->getOption('stubthreshold') ;
1517 if ( $threshold > 0 ) {
1518 $dbr =& wfGetDB( DB_SLAVE
);
1519 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1520 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1521 if ( $s !== false ) {
1523 if ( $s->cur_is_redirect
OR $s->cur_namespace
!= 0 ) {
1524 $size = $threshold*2 ; # Really big
1526 $dbr->freeResult( $res );
1528 $size = $threshold*2 ; # Really big
1533 if ( $size < $threshold ) {
1534 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1536 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1544 # Pass a title object, not a title string
1545 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '' ) {
1546 global $wgOut, $wgTitle, $wgInputEncoding;
1548 $fname = 'Skin::makeKnownLinkObj';
1549 wfProfileIn( $fname );
1551 if ( !is_object( $nt ) ) {
1554 $link = $nt->getPrefixedURL();
1555 # if ( '' != $section && substr($section,0,1) != "#" ) {
1558 if ( '' == $link ) {
1560 if ( '' == $text ) {
1561 $text = htmlspecialchars( $nt->getFragment() );
1564 $u = $nt->escapeLocalURL( $query );
1566 if ( '' != $nt->getFragment() ) {
1567 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1568 $replacearray = array(
1572 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1574 if ( '' == $text ) {
1575 $text = htmlspecialchars( $nt->getPrefixedText() );
1577 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1580 if ( '' != $trail ) {
1581 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1586 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1587 wfProfileOut( $fname );
1591 # Pass a title object, not a title string
1592 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1593 global $wgOut, $wgUser;
1597 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1599 $fname = 'Skin::makeBrokenLinkObj';
1600 wfProfileIn( $fname );
1602 if ( '' == $query ) {
1605 $q = 'action=edit&'.$query;
1607 $u = $nt->escapeLocalURL( $q );
1609 if ( '' == $text ) {
1610 $text = htmlspecialchars( $nt->getPrefixedText() );
1612 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1615 if ( '' != $trail ) {
1616 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1621 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1622 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1624 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1627 wfProfileOut( $fname );
1631 # Pass a title object, not a title string
1632 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1633 global $wgOut, $wgUser;
1635 $link = $nt->getPrefixedURL();
1637 $u = $nt->escapeLocalURL( $query );
1639 if ( '' == $text ) {
1640 $text = htmlspecialchars( $nt->getPrefixedText() );
1642 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1645 if ( '' != $trail ) {
1646 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1651 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1652 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1654 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1659 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1660 $u = $nt->escapeLocalURL( $query );
1661 if ( '' == $text ) {
1662 $text = htmlspecialchars( $nt->getPrefixedText() );
1665 if ( '' != $trail ) {
1666 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1671 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1674 /* these are used extensively in SkinPHPTal, but also some other places */
1675 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1676 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1677 $this->checkTitle($title, $name);
1678 return $title->getLocalURL( $urlaction );
1680 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1681 $title = Title
::newFromText( $name );
1682 $title = $title->getTalkPage();
1683 $this->checkTitle($title, $name);
1684 return $title->getLocalURL( $urlaction );
1686 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1687 $title = Title
::newFromText( $name );
1688 $title= $title->getSubjectPage();
1689 $this->checkTitle($title, $name);
1690 return $title->getLocalURL( $urlaction );
1692 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1693 $title = Title
::newFromText( wfMsg($name) );
1694 $this->checkTitle($title, $name);
1695 return $title->getLocalURL( $urlaction );
1697 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1698 $title = Title
::newFromText( $name );
1699 $this->checkTitle($title, $name);
1700 return $title->getLocalURL( $urlaction );
1702 # this can be passed the NS number as defined in Language.php
1703 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1704 $title = Title
::makeTitleSafe( $namespace, $name );
1705 $this->checkTitle($title, $name);
1706 return $title->getLocalURL( $urlaction );
1709 /* these return an array with the 'href' and boolean 'exists' */
1710 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1711 $title = Title
::newFromText( $name );
1712 $this->checkTitle($title, $name);
1714 'href' => $title->getLocalURL( $urlaction ),
1715 'exists' => $title->getArticleID() != 0?
true:false
1718 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1719 $title = Title
::newFromText( $name );
1720 $title = $title->getTalkPage();
1721 $this->checkTitle($title, $name);
1723 'href' => $title->getLocalURL( $urlaction ),
1724 'exists' => $title->getArticleID() != 0?
true:false
1727 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1728 $title = Title
::newFromText( $name );
1729 $title= $title->getSubjectPage();
1730 $this->checkTitle($title, $name);
1732 'href' => $title->getLocalURL( $urlaction ),
1733 'exists' => $title->getArticleID() != 0?
true:false
1736 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1737 $title = Title
::newFromText( wfMsg($name) );
1738 $this->checkTitle($title, $name);
1740 'href' => $title->getLocalURL( $urlaction ),
1741 'exists' => $title->getArticleID() != 0?
true:false
1745 # make sure we have some title to operate on
1746 /*static*/ function checkTitle ( &$title, &$name ) {
1747 if(!is_object($title)) {
1748 $title = Title
::newFromText( $name );
1749 if(!is_object($title)) {
1750 $title = Title
::newFromText( '--error: link target missing--' );
1755 function fnamePart( $url ) {
1756 $basename = strrchr( $url, '/' );
1757 if ( false === $basename ) {
1760 $basename = substr( $basename, 1 );
1762 return htmlspecialchars( $basename );
1765 function makeImage( $url, $alt = '' ) {
1769 $alt = $this->fnamePart( $url );
1771 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1775 function makeImageLink( $name, $url, $alt = '' ) {
1776 $nt = Title
::makeTitleSafe( NS_IMAGE
, $name );
1777 return $this->makeImageLinkObj( $nt, $alt );
1780 function makeImageLinkObj( $nt, $alt = '' ) {
1781 global $wgLang, $wgUseImageResize;
1782 $img = Image
::newFromTitle( $nt );
1783 $url = $img->getURL();
1786 $prefix = $postfix = '';
1788 if ( $wgUseImageResize ) {
1789 # Check if the alt text is of the form "options|alt text"
1791 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1792 # * left no resizing, just left align. label is used for alt= only
1793 # * right same, but right aligned
1794 # * none same, but not aligned
1795 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1796 # * center center the image
1797 # * framed Keep original image size, no magnify-button.
1799 $part = explode( '|', $alt);
1801 $mwThumb =& MagicWord
::get( MAG_IMG_THUMBNAIL
);
1802 $mwLeft =& MagicWord
::get( MAG_IMG_LEFT
);
1803 $mwRight =& MagicWord
::get( MAG_IMG_RIGHT
);
1804 $mwNone =& MagicWord
::get( MAG_IMG_NONE
);
1805 $mwWidth =& MagicWord
::get( MAG_IMG_WIDTH
);
1806 $mwCenter =& MagicWord
::get( MAG_IMG_CENTER
);
1807 $mwFramed =& MagicWord
::get( MAG_IMG_FRAMED
);
1808 $alt = $part[count($part)-1];
1810 $height = $framed = $thumb = false;
1811 $manual_thumb = "" ;
1813 foreach( $part as $key => $val ) {
1814 $val_parts = explode ( "=" , $val , 2 ) ;
1815 $left_part = array_shift ( $val_parts ) ;
1816 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1818 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1819 # use manually specified thumbnail
1821 $manual_thumb = array_shift ( $val_parts ) ;
1822 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1823 # remember to set an alignment, don't render immediately
1825 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1826 # remember to set an alignment, don't render immediately
1828 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1829 # remember to set an alignment, don't render immediately
1831 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1832 # remember to set an alignment, don't render immediately
1834 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1835 # $match is the image width in pixels
1836 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1837 $width = intval( $m[1] );
1838 $height = intval( $m[2] );
1840 $width = intval($match);
1842 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1846 if ( 'center' == $align )
1848 $prefix = '<span style="text-align: center">';
1849 $postfix = '</span>';
1853 if ( $thumb ||
$framed ) {
1855 # Create a thumbnail. Alignment depends on language
1856 # writing direction, # right aligned for left-to-right-
1857 # languages ("Western languages"), left-aligned
1858 # for right-to-left-languages ("Semitic languages")
1860 # If thumbnail width has not been provided, it is set
1861 # here to 180 pixels
1862 if ( $align == '' ) {
1863 $align = $wgLang->isRTL() ?
'left' : 'right';
1865 if ( ! isset($width) ) {
1868 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1870 } elseif ( isset($width) ) {
1872 # Create a resized image, without the additional thumbnail
1875 if ( ( ! $height === false )
1876 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1877 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1878 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1879 $width = $img->getWidth() * $height / $img->getHeight();
1881 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1883 } # endif $wgUseImageResize
1885 if ( empty( $alt ) ) {
1886 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1888 $alt = htmlspecialchars( $alt );
1890 $u = $nt->escapeLocalURL();
1893 $s = wfMsg( 'missingimage', $img->getName() );
1894 $s .= "<br>{$alt}<br>{$url}<br>\n";
1896 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1897 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1899 if ( '' != $align ) {
1900 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1902 return str_replace("\n", ' ',$prefix.$s.$postfix);
1905 # Make HTML for a thumbnail including image, border and caption
1906 # $img is an Image object
1907 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1908 global $wgStylePath, $wgLang;
1909 # $image = Title::makeTitleSafe( NS_IMAGE, $name );
1910 $url = $img->getURL();
1912 #$label = htmlspecialchars( $label );
1913 $alt = preg_replace( '/<[^>]*>/', '', $label);
1914 $alt = htmlspecialchars( $alt );
1916 $width = $height = 0;
1917 if ( $img->exists() )
1919 $width = $img->getWidth();
1920 $height = $img->getHeight();
1922 if ( 0 == $width ||
0 == $height )
1924 $width = $height = 200;
1926 if ( $boxwidth == 0 )
1932 // Use image dimensions, don't scale
1934 $oboxwidth = $boxwidth +
2;
1935 $boxheight = $height;
1938 $h = intval( $height/($width/$boxwidth) );
1939 $oboxwidth = $boxwidth +
2;
1940 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1942 $boxwidth *= $boxheight/$h;
1946 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1949 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1951 $manual_title = Title
::makeTitleSafe( NS_IMAGE
, $manual_thumb ); #new Title ( $manual_thumb ) ;
1952 $manual_img = Image
::newFromTitle( $manual_title );
1953 $thumbUrl = $manual_img->getURL();
1954 if ( $manual_img->exists() )
1956 $width = $manual_img->getWidth();
1957 $height = $manual_img->getHeight();
1958 $boxwidth = $width ;
1959 $boxheight = $height ;
1960 $oboxwidth = $boxwidth +
2 ;
1964 $u = $img->getEscapeLocalURL();
1966 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1967 $magnifyalign = $wgLang->isRTL() ?
'left' : 'right';
1968 $textalign = $wgLang->isRTL() ?
' style="text-align:right"' : '';
1970 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1971 if ( $thumbUrl == '' ) {
1972 $s .= wfMsg( 'missingimage', $img->getName() );
1975 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1976 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1977 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1981 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1982 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1983 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1984 'width="15" height="11" alt="'.$more.'" /></a></div>';
1987 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1988 return str_replace("\n", ' ', $s);
1991 function makeMediaLink( $name, $url, $alt = '' ) {
1992 $nt = Title
::makeTitleSafe( Namespace::getMedia(), $name );
1993 return $this->makeMediaLinkObj( $nt, $alt );
1996 function makeMediaLinkObj( $nt, $alt = '' ) {
1997 if ( ! isset( $nt ) )
1999 ### HOTFIX. Instead of breaking, return empty string.
2002 $name = $nt->getDBKey();
2003 $url = Image
::wfImageUrl( $name );
2004 if ( empty( $alt ) ) {
2005 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2008 $u = htmlspecialchars( $url );
2009 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2014 function specialLink( $name, $key = '' ) {
2017 if ( '' == $key ) { $key = strtolower( $name ); }
2018 $pn = $wgLang->ucfirst( $name );
2019 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2023 function makeExternalLink( $url, $text, $escape = true ) {
2024 $style = $this->getExternalLinkAttributes( $url, $text );
2025 $url = htmlspecialchars( $url );
2027 $text = htmlspecialchars( $text );
2029 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2032 # Called by history lists and recent changes
2035 # Returns text for the start of the tabular part of RC
2036 function beginRecentChangesList() {
2037 $this->rc_cache
= array() ;
2038 $this->rcMoveIndex
= 0;
2039 $this->rcCacheIndex
= 0 ;
2040 $this->lastdate
= '';
2041 $this->rclistOpen
= false;
2045 function beginImageHistoryList() {
2046 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2047 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2051 # Returns text for the end of RC
2052 # If enhanced RC is in use, returns pretty much all the text
2053 function endRecentChangesList() {
2054 $s = $this->recentChangesBlock() ;
2055 if( $this->rclistOpen
) {
2061 # Enhanced RC ungrouped line
2062 function recentChangesBlockLine ( $rcObj ) {
2063 global $wgStylePath, $wgLang ;
2065 # Get rc_xxxx variables
2066 extract( $rcObj->mAttribs
) ;
2067 $curIdEq = 'curid='.$rc_cur_id;
2072 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2075 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2076 $r .= ' ';
2078 # M & N (minor & new)
2079 $M = wfMsg( 'minoreditletter' );
2080 $N = wfMsg( 'newpageletter' );
2082 if ( $rc_type == RC_NEW
) {
2095 $r .= ' '.$rcObj->timestamp
.' ' ;
2099 $link = $rcObj->link
;
2100 if ( $rcObj->watched
) $link = '<strong>'.$link.'</strong>' ;
2105 $r .= $rcObj->difflink
;
2109 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2112 $r .= ') . . '.$rcObj->userlink
;
2113 $r .= $rcObj->usertalklink
;
2116 if ( $rc_comment != '' && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2117 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2118 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2126 function recentChangesBlockGroup ( $block ) {
2127 global $wgStylePath, $wgLang ;
2130 $M = wfMsg( 'minoreditletter' );
2131 $N = wfMsg( 'newpageletter' );
2133 # Collate list of users
2135 $userlinks = array () ;
2136 foreach ( $block AS $rcObj ) {
2137 $oldid = $rcObj->mAttribs
['rc_last_oldid'];
2138 if ( $rcObj->mAttribs
['rc_new'] ) $isnew = true ;
2139 $u = $rcObj->userlink
;
2140 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2144 # Sort the list and convert to text
2145 krsort ( $userlinks ) ;
2146 asort ( $userlinks ) ;
2148 foreach ( $userlinks as $userlink => $count) {
2150 if ( $count > 1 ) $text .= " ({$count}×)" ;
2151 array_push ( $users , $text ) ;
2153 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2156 $rci = 'RCI'.$this->rcCacheIndex
;
2157 $rcl = 'RCL'.$this->rcCacheIndex
;
2158 $rcm = 'RCM'.$this->rcCacheIndex
;
2159 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2160 $arrowdir = $wgLang->isRTL() ?
'l' : 'r';
2161 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2162 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2168 if ( $isnew ) $r .= $N ;
2169 else $r .= ' ' ;
2170 $r .= ' ' ; # Minor
2173 $r .= ' '.$block[0]->timestamp
.' ' ;
2177 $link = $block[0]->link
;
2178 if ( $block[0]->watched
) $link = '<strong>'.$link.'</strong>' ;
2181 $curIdEq = 'curid=' . $block[0]->mAttribs
['rc_cur_id'];
2182 if ( $block[0]->mAttribs
['rc_type'] != RC_LOG
) {
2184 $r .= ' ('.count($block).' ' ;
2185 if ( $isnew ) $r .= wfMsg('changes');
2186 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2187 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2191 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2199 $r .= '<div id="'.$rci.'" style="display:none">' ;
2200 foreach ( $block AS $rcObj ) {
2201 # Get rc_xxxx variables
2202 extract( $rcObj->mAttribs
);
2204 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2205 $r .= '<tt> ' ;
2206 if ( $rc_new ) $r .= $N ;
2207 else $r .= ' ' ;
2208 if ( $rc_minor ) $r .= $M ;
2209 else $r .= ' ' ;
2213 if ( $rc_last_oldid != 0 ) {
2214 $o = 'oldid='.$rc_last_oldid ;
2216 if ( $rc_type == RC_LOG
) {
2217 $link = $rcObj->timestamp
;
2219 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp
, "{$curIdEq}&$o" ) ;
2221 $link = '<tt>'.$link.'</tt>' ;
2225 $r .= $rcObj->curlink
;
2227 $r .= $rcObj->lastlink
;
2228 $r .= ') . . '.$rcObj->userlink
;
2229 $r .= $rcObj->usertalklink
;
2230 if ( $rc_comment != '' ) {
2231 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2232 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2238 $this->rcCacheIndex++
;
2242 # If enhanced RC is in use, this function takes the previously cached
2243 # RC lines, arranges them, and outputs the HTML
2244 function recentChangesBlock () {
2245 global $wgStylePath ;
2246 if ( count ( $this->rc_cache
) == 0 ) return '' ;
2248 foreach ( $this->rc_cache
AS $secureName => $block ) {
2249 if ( count ( $block ) < 2 ) {
2250 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2252 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2256 return '<div>'.$blockOut.'</div>' ;
2259 # Called in a loop over all displayed RC entries
2260 # Either returns the line, or caches it for later use
2261 function recentChangesLine( &$rc, $watched = false ) {
2263 $usenew = $wgUser->getOption( 'usenewrc' );
2265 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2267 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2271 function recentChangesLineOld( &$rc, $watched = false ) {
2272 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2274 # Extract DB fields into local scope
2275 extract( $rc->mAttribs
);
2276 $curIdEq = 'curid=' . $rc_cur_id;
2278 # Make date header if necessary
2279 $date = $wgLang->date( $rc_timestamp, true);
2281 if ( $date != $this->lastdate
) {
2282 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2283 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2284 $this->lastdate
= $date;
2285 $this->rclistOpen
= true;
2288 # If this edit has not yet been patrolled, make it stick out
2289 $s .= ( ! $wgUseRCPatrol ||
$rc_patrolled ) ?
'<li> ' : '<li class="not_patrolled"> ';
2291 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2293 $s .= '(' . wfMsg( 'diff' ) . ') (';
2295 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2298 # "[[x]] moved to [[y]]"
2299 $msg = ( $rc_type == RC_MOVE
) ?
'1movedto2' : '1movedto2_redir';
2300 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2301 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2302 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2304 $logtype = $matches[1];
2305 $logname = LogPage
::logName( $logtype );
2306 $s .= '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2309 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2310 $diffLink = wfMsg( 'diff' );
2312 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2313 ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2314 $rcidparam = "&rcid={$rc_id}";
2317 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2318 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2319 '', '', ' tabindex="'.$rc->counter
.'"');
2321 $s .= '('.$diffLink.') (';
2324 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2327 # M and N (minor and new)
2328 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2329 if ( $rc_type == RC_NEW
) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2332 # If it's a new article, there is no diff link, but if it hasn't been
2333 # patrolled yet, we need to give users a way to do so
2334 if ( $wgUseRCPatrol && $rc_type == RC_NEW
&& $rc_patrolled == 0 &&
2335 $wgUser->getID() != 0 && ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2336 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2338 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2341 $articleLink = '<strong>'.$articleLink.'</strong>';
2343 $s .= ' '.$articleLink;
2348 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2350 # User link (or contributions for unregistered users)
2351 if ( 0 == $rc_user ) {
2352 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2353 $rc_user_text, 'target=' . $rc_user_text );
2355 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2360 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2361 global $wgDisableAnonTalk;
2362 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2365 $utns=$wgLang->getNsText(NS_USER_TALK
);
2366 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2370 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2371 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2372 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2376 if($userTalkLink) $userTalkLink .= ' | ';
2377 $userTalkLink .= $blockLink;
2379 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2382 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2383 $rc_comment=$this->formatComment($rc_comment,$rc->getTitle());
2384 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2391 function recentChangesLineNew( &$baseRC, $watched = false ) {
2392 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2394 # Create a specialised object
2395 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2397 # Extract fields from DB into the function scope (rc_xxxx variables)
2398 extract( $rc->mAttribs
);
2399 $curIdEq = 'curid=' . $rc_cur_id;
2401 # If it's a new day, add the headline and flush the cache
2402 $date = $wgLang->date( $rc_timestamp, true);
2404 if ( $date != $this->lastdate
) {
2405 # Process current cache
2406 $ret = $this->recentChangesBlock () ;
2407 $this->rc_cache
= array() ;
2408 $ret .= "<h4>{$date}</h4>\n";
2409 $this->lastdate
= $date;
2413 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2414 $msg = ( $rc_type == RC_MOVE
) ?
"1movedto2" : "1movedto2_redir";
2415 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2416 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2417 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2419 $logtype = $matches[1];
2420 $logname = LogPage
::logName( $logtype );
2421 $clink = '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2423 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2426 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2427 $rc->watched
= $watched ;
2428 $rc->link
= $clink ;
2429 $rc->timestamp
= $time;
2431 # Make "cur" and "diff" links
2432 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2433 $curLink = wfMsg( 'cur' );
2434 $diffLink = wfMsg( 'diff' );
2436 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2437 $aprops = ' tabindex="'.$baseRC->counter
.'"';
2438 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2439 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2443 $titleObj = $rc->getTitle();
2444 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2445 $lastLink = wfMsg( 'last' );
2447 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2448 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2451 # Make user link (or user contributions for unregistered users)
2452 if ( $rc_user == 0 ) {
2453 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2454 $rc_user_text, 'target=' . $rc_user_text );
2456 $userLink = $this->makeLink( $wgLang->getNsText(
2457 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2460 $rc->userlink
= $userLink;
2461 $rc->lastlink
= $lastLink;
2462 $rc->curlink
= $curLink;
2463 $rc->difflink
= $diffLink;
2465 # Make user talk link
2466 $utns=$wgLang->getNsText(NS_USER_TALK
);
2467 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2468 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2470 global $wgDisableAnonTalk;
2471 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2472 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2473 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2474 if( $wgDisableAnonTalk )
2475 $rc->usertalklink
= ' ('.$blockLink.')';
2477 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2479 if( $wgDisableAnonTalk && ($rc_user == 0) )
2480 $rc->usertalklink
= '';
2482 $rc->usertalklink
= ' ('.$userTalkLink.')';
2485 # Put accumulated information into the cache, for later display
2486 # Page moves go on their own line
2487 $title = $rc->getTitle();
2488 $secureName = $title->getPrefixedDBkey();
2489 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2490 # Use an @ character to prevent collision with page names
2491 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2493 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2494 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2499 function endImageHistoryList() {
2504 /* This function is called by all recent changes variants, by the page history,
2505 and by the user contributions list. It is responsible for formatting edit
2506 comments. It escapes any HTML in the comment, but adds some CSS to format
2507 auto-generated comments (from section editing) and formats [[wikilinks]].
2509 The &$title parameter must be a title OBJECT. It is used to generate a
2510 direct link to the section in the autocomment.
2511 Main author: Erik Moeller (moeller@scireview.de)
2513 # Note: there's not always a title to pass to this function.
2514 # Since you can't set a default parameter for a reference, I've turned it
2515 # temporarily to a value pass. Should be adjusted further. --brion
2516 function formatComment($comment, $title = NULL) {
2518 $comment = htmlspecialchars( $comment );
2520 # The pattern for autogen comments is / * foo * /, which makes for
2522 # We look for all comments, match any text before and after the comment,
2523 # add a separator where needed and format the comment itself with CSS
2524 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2532 # This is hackish but should work in most cases.
2533 $section=str_replace('[[','',$section);
2534 $section=str_replace(']]','',$section);
2535 $title->mFragment
=$section;
2536 $link=$this->makeKnownLinkObj($title,wfMsg('sectionlink'));
2540 if($pre) { $auto = $sep.' '.$auto; }
2541 if($post) { $auto .= ' '.$sep; }
2542 $auto='<span class="autocomment">'.$auto.'</span>';
2543 $comment=$pre.$auto.$post;
2546 # format regular and media links - all other wiki formatting
2548 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2549 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2550 # Handle link renaming [[foo|text]] will show link as "text"
2551 if( "" != $match[3] ) {
2556 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2557 # Media link; trail not supported.
2558 $linkRegexp = '/\[\[(.*?)\]\]/';
2559 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2561 # Other kind of link
2562 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2563 $trail = $submatch[1];
2567 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2568 if ($match[1][0] == ':')
2569 $match[1] = substr($match[1], 1);
2570 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2572 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2577 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description ) {
2578 global $wgUser, $wgLang, $wgTitle;
2580 $datetime = $wgLang->timeanddate( $timestamp, true );
2581 $del = wfMsg( 'deleteimg' );
2582 $delall = wfMsg( 'deleteimgcompletely' );
2583 $cur = wfMsg( 'cur' );
2586 $url = Image
::wfImageUrl( $img );
2588 if ( $wgUser->isSysop() ) {
2589 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2591 $style = $this->getInternalLinkAttributes( $link, $delall );
2593 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2598 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2599 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2600 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2601 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2602 urlencode( $img ) );
2603 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2604 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2606 # Having live active links for non-logged in users
2607 # means that bots and spiders crawling our site can
2608 # inadvertently change content. Baaaad idea.
2609 $rlink = wfMsg( 'revertimg' );
2614 $userlink = $usertext;
2616 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2617 ':'.$usertext, $usertext );
2619 $nbytes = wfMsg( 'nbytes', $size );
2620 $style = $this->getInternalLinkAttributes( $url, $datetime );
2622 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2623 . " . . {$userlink} ({$nbytes})";
2625 if ( '' != $description && '*' != $description ) {
2626 $sk=$wgUser->getSkin();
2627 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description,$wgTitle) . ')');
2633 function tocIndent($level) {
2634 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2637 function tocUnindent($level) {
2638 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2641 # parameter level defines if we are on an indentation level
2642 function tocLine( $anchor, $tocline, $level ) {
2643 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2647 return '<div class="tocline">'.$link."</div>\n";
2652 function tocTable($toc) {
2653 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2654 # try min-width & co when somebody gets a chance
2655 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2657 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2658 '<b>'.wfMsg('toc').'</b>' .
2660 '</td></tr><tr id="tocinside"><td>'."\n".
2661 $toc."</td></tr></table>\n";
2664 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2665 function editSectionScript( $section, $head ) {
2666 global $wgTitle, $wgRequest;
2667 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2670 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2671 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2674 function editSectionLink( $section ) {
2676 global $wgTitle, $wgUser, $wgLang;
2678 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2679 # Section edit links would be out of sync on an old page.
2680 # But, if we're diffing to the current page, they'll be
2685 $editurl = '§ion='.$section;
2686 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2688 if( $wgLang->isRTL() ) {
2690 $nearside = 'right';
2695 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2699 // This function is called by EditPage.php and shows a bulletin board style
2700 // toolbar for common editing functions. It can be disabled in the user preferences.
2701 // The necsesary JavaScript code can be found in style/wikibits.js.
2702 function getEditToolbar() {
2703 global $wgStylePath, $wgLang, $wgMimeType;
2705 // toolarray an array of arrays which each include the filename of
2706 // the button image (without path), the opening tag, the closing tag,
2707 // and optionally a sample text that is inserted between the two when no
2708 // selection is highlighted.
2709 // The tip text is shown when the user moves the mouse over the button.
2711 // Already here are accesskeys (key), which are not used yet until someone
2712 // can figure out a way to make them work in IE. However, we should make
2713 // sure these keys are not defined on the edit page.
2715 array( 'image'=>'button_bold.png',
2717 'close' => "\'\'\'",
2718 'sample'=> wfMsg('bold_sample'),
2719 'tip' => wfMsg('bold_tip'),
2722 array( 'image'=>'button_italic.png',
2725 'sample'=> wfMsg('italic_sample'),
2726 'tip' => wfMsg('italic_tip'),
2729 array( 'image'=>'button_link.png',
2732 'sample'=> wfMsg('link_sample'),
2733 'tip' => wfMsg('link_tip'),
2736 array( 'image'=>'button_extlink.png',
2739 'sample'=> wfMsg('extlink_sample'),
2740 'tip' => wfMsg('extlink_tip'),
2743 array( 'image'=>'button_headline.png',
2745 'close' => " ==\\n",
2746 'sample'=> wfMsg('headline_sample'),
2747 'tip' => wfMsg('headline_tip'),
2750 array( 'image'=>'button_image.png',
2751 'open' => '[['.$wgLang->getNsText(NS_IMAGE
).":",
2753 'sample'=> wfMsg('image_sample'),
2754 'tip' => wfMsg('image_tip'),
2757 array( 'image' => 'button_media.png',
2758 'open' => '[['.$wgLang->getNsText(NS_MEDIA
).':',
2760 'sample'=> wfMsg('media_sample'),
2761 'tip' => wfMsg('media_tip'),
2764 array( 'image' => 'button_math.png',
2765 'open' => "\\<math\\>",
2766 'close' => "\\</math\\>",
2767 'sample'=> wfMsg('math_sample'),
2768 'tip' => wfMsg('math_tip'),
2771 array( 'image' => 'button_nowiki.png',
2772 'open' => "\\<nowiki\\>",
2773 'close' => "\\</nowiki\\>",
2774 'sample'=> wfMsg('nowiki_sample'),
2775 'tip' => wfMsg('nowiki_tip'),
2778 array( 'image' => 'button_sig.png',
2782 'tip' => wfMsg('sig_tip'),
2785 array( 'image' => 'button_hr.png',
2786 'open' => "\\n----\\n",
2789 'tip' => wfMsg('hr_tip'),
2793 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2795 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2796 foreach($toolarray as $tool) {
2798 $image=$wgStylePath.'/images/'.$tool['image'];
2799 $open=$tool['open'];
2800 $close=$tool['close'];
2801 $sample = addslashes( $tool['sample'] );
2803 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2804 // Older browsers show a "speedtip" type message only for ALT.
2805 // Ideally these should be different, realistically they
2806 // probably don't need to be.
2807 $tip = addslashes( $tool['tip'] );
2809 #$key = $tool["key"];
2811 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2814 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2815 $toolbar.="document.writeln(\"</div>\");\n";
2817 $toolbar.="/*]]>*/\n</script>";
2821 /* public */ function suppressUrlExpansion() {