7450f1d5501da889b4e74f3f6c52fb4fa44886ec
8 * This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
10 if( defined( "MEDIAWIKI" ) ) {
14 require_once( 'Feed.php' ); // should not be called if the actual page isn't feed enabled
15 require_once( 'Image.php' );
17 # These are the INTERNAL names, which get mapped directly to class names and
18 # file names in ./skins/. For display purposes, the Language class has
19 # internationalized names
22 $wgValidSkinNames = array(
23 'standard' => 'Standard',
24 'nostalgia' => 'Nostalgia',
25 'cologneblue' => 'CologneBlue'
28 #$wgValidSkinNames[] = 'PHPTal';
29 #$wgValidSkinNames['davinci'] = 'DaVinci';
30 #$wgValidSkinNames['mono'] = 'Mono';
31 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
32 $wgValidSkinNames['monobook'] = 'MonoBook';
33 $wgValidSkinNames['myskin'] = 'MySkin';
34 $wgValidSkinNames['chick'] = 'Chick';
38 # Get a list of all skins available in /skins/
39 # Build using the regular expression '^(.*).php$'
40 # Array keys are all lower case, array value keep the case used by filename
43 $skinDir = dir($IP.'/skins');
45 # while code from www.php.net
46 while (false !== ($file = $skinDir->read())) {
47 if(preg_match('/^(.*).php$/',$file, $matches)) {
49 $wgValidSkinNames[strtolower($aSkin)] = $aSkin;
55 require_once( 'RecentChange.php' );
60 class RCCacheEntry
extends RecentChange
62 var $secureName, $link;
63 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
64 var $userlink, $timestamp, $watched;
66 function newFromParent( $rc )
68 $rc2 = new RCCacheEntry
;
69 $rc2->mAttribs
= $rc->mAttribs
;
70 $rc2->mExtra
= $rc->mExtra
;
77 * The main skin class that provide methods and properties for all other skins
78 * including PHPTal skins.
79 * This base class is also the "Standard" skin.
85 var $lastdate, $lastline;
86 var $linktrail ; # linktrail regexp
87 var $rc_cache ; # Cache for Enhanced Recent Changes
88 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
90 var $postParseLinkColour = true;
94 global $wgUseOldExistenceCheck;
95 $postParseLinkColour = !$wgUseOldExistenceCheck;
96 $this->linktrail
= wfMsg('linktrail');
99 function getSkinNames() {
100 global $wgValidSkinNames;
101 return $wgValidSkinNames;
104 function getStylesheet() {
105 return 'wikistandard.css';
108 function getSkinName() {
113 * Get/set accessor for delayed link colouring
115 function postParseLinkColour( $setting = NULL ) {
116 return wfSetVar( $this->postParseLinkColour
, $setting );
119 function qbSetting() {
120 global $wgOut, $wgUser;
122 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
123 $q = $wgUser->getOption( 'quickbar' );
124 if ( '' == $q ) { $q = 0; }
128 function initPage( &$out ) {
129 $fname = 'Skin::initPage';
130 wfProfileIn( $fname );
132 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
134 $this->addMetadataLinks($out);
136 wfProfileOut( $fname );
139 function addMetadataLinks( &$out ) {
140 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
141 global $wgRightsPage, $wgRightsUrl;
143 if( $out->isArticleRelated() ) {
144 # note: buggy CC software only reads first "meta" link
145 if( $wgEnableCreativeCommonsRdf ) {
146 $out->addMetadataLink( array(
147 'title' => 'Creative Commons',
148 'type' => 'application/rdf+xml',
149 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
151 if( $wgEnableDublinCoreRdf ) {
152 $out->addMetadataLink( array(
153 'title' => 'Dublin Core',
154 'type' => 'application/rdf+xml',
155 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
159 if( $wgRightsPage ) {
160 $copy = Title
::newFromText( $wgRightsPage );
162 $copyright = $copy->getLocalURL();
165 if( !$copyright && $wgRightsUrl ) {
166 $copyright = $wgRightsUrl;
169 $out->addLink( array(
170 'rel' => 'copyright',
171 'href' => $copyright ) );
175 function outputPage( &$out ) {
176 global $wgDebugComments;
178 wfProfileIn( 'Skin::outputPage' );
179 $this->initPage( $out );
180 $out->out( $out->headElement() );
182 $out->out( "\n<body" );
183 $ops = $this->getBodyOptions();
184 foreach ( $ops as $name => $val ) {
185 $out->out( " $name='$val'" );
188 if ( $wgDebugComments ) {
189 $out->out( "<!-- Wiki debugging output:\n" .
190 $out->mDebugtext
. "-->\n" );
192 $out->out( $this->beforeContent() );
194 $out->out( $out->mBodytext
. "\n" );
196 $out->out( $this->afterContent() );
199 $out->out( $out->reportTime() );
201 $out->out( "\n</body></html>" );
204 function getHeadScripts() {
205 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
206 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
207 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
208 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
209 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
210 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
215 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
216 function getUserStylesheet() {
217 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
218 $sheet = $this->getStylesheet();
219 $action = $wgRequest->getText('action');
220 $s = "@import \"$wgStylePath/$sheet\";\n";
221 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
222 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
223 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
224 $s .= $wgRequest->getText('wpTextbox1');
226 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
227 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
230 $s .= $this->doGetUserStyles();
235 * placeholder, returns generated js in monobook
237 function getUserJs() { return; }
240 * Return html code that include User stylesheets
242 function getUserStyles() {
243 global $wgOut, $wgStylePath, $wgLang;
244 $s = "<style type='text/css'>\n";
245 $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
246 $s .= $this->getUserStylesheet();
247 $s .= "/*]]>*/ /* */\n";
253 * Some styles that are set by user through the user settings interface.
255 function doGetUserStyles() {
256 global $wgUser, $wgLang;
258 $csspage = $wgLang->getNsText( NS_MEDIAWIKI
) . ':' . $this->getSkinName() . '.css';
259 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
261 if ( 1 == $wgUser->getOption( 'underline' ) ) {
262 # Don't override browser settings
266 $s .= "a { text-decoration: none; }\n";
268 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
269 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
271 if ( 1 == $wgUser->getOption( 'justify' ) ) {
272 $s .= "#article { text-align: justify; }\n";
277 function getBodyOptions() {
278 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
280 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
282 if ( 0 != $wgTitle->getNamespace() ) {
283 $a = array( 'bgcolor' => '#ffffec' );
285 else $a = array( 'bgcolor' => '#FFFFFF' );
286 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
287 (!$wgTitle->isProtected() ||
$wgUser->isSysop()) ) {
288 $t = wfMsg( 'editthispage' );
290 if ( !empty($redirect) ) {
291 $red = "&redirect={$redirect}";
293 if ( !empty($oldid) && ! isset( $diff ) ) {
294 $oid = "&oldid={$oldid}";
296 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
297 $s = 'document.location = "' .$s .'";';
298 $a +
= array ('ondblclick' => $s);
301 $a['onload'] = $wgOut->getOnloadHandler();
305 function getExternalLinkAttributes( $link, $text, $class='' ) {
306 global $wgUser, $wgOut, $wgLang;
308 $link = urldecode( $link );
309 $link = $wgLang->checkTitleEncoding( $link );
310 $link = str_replace( '_', ' ', $link );
311 $link = htmlspecialchars( $link );
313 $r = ($class != '') ?
" class='$class'" : " class='external'";
315 if ( 1 == $wgUser->getOption( 'hover' ) ) {
316 $r .= " title=\"{$link}\"";
321 function getInternalLinkAttributes( $link, $text, $broken = false ) {
322 global $wgUser, $wgOut;
324 $link = urldecode( $link );
325 $link = str_replace( '_', ' ', $link );
326 $link = htmlspecialchars( $link );
328 if ( $broken == 'stub' ) {
329 $r = ' class="stub"';
330 } else if ( $broken == 'yes' ) {
336 if ( 1 == $wgUser->getOption( 'hover' ) ) {
337 $r .= " title=\"{$link}\"";
343 * @param bool $broken
345 function getInternalLinkAttributesObj( &$nt, $text, $broken = false ) {
346 global $wgUser, $wgOut;
348 if ( $broken == 'stub' ) {
349 $r = ' class="stub"';
350 } else if ( $broken == 'yes' ) {
356 if ( 1 == $wgUser->getOption( 'hover' ) ) {
357 $r .= ' title ="' . $nt->getEscapedText() . '"';
371 * This will be called immediately after the <body> tag. Split into
372 * two functions to make it easier to subclass.
374 function beforeContent() {
375 global $wgUser, $wgOut;
377 return $this->doBeforeContent();
380 function doBeforeContent() {
381 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
382 $fname = 'Skin::doBeforeContent';
383 wfProfileIn( $fname );
386 $qb = $this->qbSetting();
388 if( $langlinks = $this->otherLanguages() ) {
394 $borderhack = 'class="top"';
397 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
398 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
401 $left = ($qb == 1 ||
$qb == 3);
402 if($wgLang->isRTL()) $left = !$left;
405 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
406 $this->logoText() . '</td>';
408 $s .= $this->getQuickbarCompensator( $rows );
410 $l = $wgLang->isRTL() ?
'right' : 'left';
411 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
413 $s .= $this->topLinks() ;
414 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
416 $r = $wgLang->isRTL() ?
"left" : "right";
417 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
418 $s .= $this->nameAndLogin();
419 $s .= "\n<br />" . $this->searchForm() . "</td>";
422 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
425 if ( $shove && !$left ) { # Right
426 $s .= $this->getQuickbarCompensator( $rows );
428 $s .= "</tr>\n</table>\n</div>\n";
429 $s .= "\n<div id='article'>\n";
431 if( $wgSiteNotice ) {
432 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
434 $s .= $this->pageTitle();
435 $s .= $this->pageSubtitle() ;
436 $s .= $this->getCategories();
437 wfProfileOut( $fname );
441 function getCategoryLinks () {
442 global $wgOut, $wgTitle, $wgUser, $wgParser;
443 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
445 if( !$wgUseCategoryMagic ) return '' ;
446 if( count( $wgOut->mCategoryLinks
) == 0 ) return '';
448 # Taken out so that they will be displayed in previews -- TS
449 #if( !$wgOut->isArticle() ) return '';
451 $t = implode ( ' | ' , $wgOut->mCategoryLinks
) ;
452 $s = $this->makeKnownLink( 'Special:Categories',
453 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
456 # optional 'dmoz-like' category browser. Will be shown under the list
457 # of categories an article belong to
458 if($wgUseCategoryBrowser) {
461 # get a big array of the parents tree
462 $parenttree = $wgTitle->getCategorieBrowser();
464 # Render the array as a serie of links
465 function walkThrough ($tree) {
467 $sk = $wgUser->getSkin();
469 foreach($tree as $element => $parent) {
471 # element start a new list
474 # grab the others elements
475 $return .= walkThrough($parent);
477 # add our current element to the list
478 $eltitle = Title
::NewFromText($element);
479 # FIXME : should be makeLink() [AV]
480 $return .= $sk->makeKnownLink($element, $eltitle->getText()).' > ';
485 $s .= walkThrough($parenttree);
491 function getCategories() {
492 $catlinks=$this->getCategoryLinks();
493 if(!empty($catlinks)) {
494 return "<p class='catlinks'>{$catlinks}</p>";
498 function getQuickbarCompensator( $rows = 1 ) {
499 return "<td width='152' rowspan='{$rows}'> </td>";
502 # This gets called immediately before the </body> tag.
504 function afterContent() {
505 global $wgUser, $wgOut, $wgServer;
506 global $wgTitle, $wgLang;
508 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
509 return $printfooter . $this->doAfterContent();
512 function printSource() {
514 $url = htmlspecialchars( $wgTitle->getFullURL() );
515 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
518 function printFooter() {
519 return "<p>" . $this->printSource() .
520 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
523 function doAfterContent() {
524 global $wgUser, $wgOut, $wgLang;
525 $fname = 'Skin::doAfterContent';
526 wfProfileIn( $fname );
527 wfProfileIn( $fname.'-1' );
529 $s = "\n</div><br style=\"clear:both\" />\n";
530 $s .= "\n<div id='footer'>";
531 $s .= '<table border="0" cellspacing="0"><tr>';
533 wfProfileOut( $fname.'-1' );
534 wfProfileIn( $fname.'-2' );
536 $qb = $this->qbSetting();
538 $left = ($qb == 1 ||
$qb == 3);
539 if($wgLang->isRTL()) $left = !$left;
541 if ( $shove && $left ) { # Left
542 $s .= $this->getQuickbarCompensator();
544 wfProfileOut( $fname.'-2' );
545 wfProfileIn( $fname.'-3' );
546 $l = $wgLang->isRTL() ?
'right' : 'left';
547 $s .= "<td class='bottom' align='$l' valign='top'>";
549 $s .= $this->bottomLinks();
550 $s .= "\n<br />" . $this->mainPageLink()
551 . ' | ' . $this->aboutLink()
552 . ' | ' . $this->specialLink( 'recentchanges' )
553 . ' | ' . $this->searchForm()
554 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
557 if ( $shove && !$left ) { # Right
558 $s .= $this->getQuickbarCompensator();
560 $s .= "</tr></table>\n</div>\n</div>\n";
562 wfProfileOut( $fname.'-3' );
563 wfProfileIn( $fname.'-4' );
564 if ( 0 != $qb ) { $s .= $this->quickBar(); }
565 wfProfileOut( $fname.'-4' );
566 wfProfileOut( $fname );
570 function pageTitleLinks() {
571 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
573 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
574 $action = $wgRequest->getText( 'action' );
576 $s = $this->printableLink();
577 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
579 if ( $wgOut->isArticleRelated() ) {
580 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
581 $name = $wgTitle->getDBkey();
582 $link = htmlspecialchars( Image
::wfImageUrl( $name ) );
583 $style = $this->getInternalLinkAttributes( $link, $name );
584 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
586 # This will show the "Approve" link if $wgUseApproval=true;
587 if ( isset ( $wgUseApproval ) && $wgUseApproval )
589 $t = $wgTitle->getDBkey();
590 $name = 'Approve this article' ;
591 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
592 #htmlspecialchars( wfImageUrl( $name ) );
593 $style = $this->getExternalLinkAttributes( $link, $name );
594 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
597 if ( 'history' == $action ||
isset( $diff ) ||
isset( $oldid ) ) {
598 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
599 wfMsg( 'currentrev' ) );
602 if ( $wgUser->getNewtalk() ) {
603 # do not show "You have new messages" text when we are viewing our
606 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
607 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
608 $n =$wgUser->getName();
609 $tl = $this->makeKnownLink( $wgLang->getNsText(
610 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
611 wfMsg('newmessageslink') );
612 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
614 $wgOut->setSquidMaxage(0);
618 $undelete = $this->getUndeleteLink();
619 if( !empty( $undelete ) ) {
620 $s .= ' | '.$undelete;
625 function getUndeleteLink() {
626 global $wgUser, $wgTitle, $wgLang, $action;
627 if( $wgUser->isSysop() &&
628 (($wgTitle->getArticleId() == 0) ||
($action == "history")) &&
629 ($n = $wgTitle->isDeleted() ) ) {
630 return wfMsg( 'thisisdeleted',
631 $this->makeKnownLink(
632 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
633 wfMsg( 'restorelink', $n ) ) );
638 function printableLink() {
639 global $wgOut, $wgFeedClasses, $wgRequest;
641 $baseurl = $_SERVER['REQUEST_URI'];
642 if( strpos( '?', $baseurl ) == false ) {
647 $baseurl = htmlspecialchars( $baseurl );
648 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
650 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
651 if( $wgOut->isSyndicated() ) {
652 foreach( $wgFeedClasses as $format => $class ) {
653 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
654 $s .= " | <a href=\"$feedurl\">{$format}</a>";
660 function pageTitle() {
661 global $wgOut, $wgTitle, $wgUser;
663 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
664 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
668 function pageSubtitle() {
671 $sub = $wgOut->getSubtitle();
673 global $wgExtraSubtitle;
674 $sub = wfMsg( 'tagline' ) . $wgExtraSubtitle;
676 $subpages = $this->subPageSubtitle();
677 $sub .= !empty($subpages)?
"</p><p class='subpages'>$subpages":'';
678 $s = "<p class='subtitle'>{$sub}</p>\n";
682 function subPageSubtitle() {
683 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
685 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
686 $ptext=$wgTitle->getPrefixedText();
687 if(preg_match('/\//',$ptext)) {
688 $links = explode('/',$ptext);
691 foreach($links as $link) {
693 if ($c<count($links)) {
694 $growinglink .= $link;
695 $getlink = $this->makeLink( $growinglink, $link );
696 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
700 $subpages .= '< ';
702 $subpages .= $getlink;
711 function nameAndLogin() {
712 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
714 $li = $wgLang->specialPage( 'Userlogin' );
715 $lo = $wgLang->specialPage( 'Userlogout' );
718 if ( 0 == $wgUser->getID() ) {
719 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
722 $tl = $this->makeKnownLink( $wgLang->getNsText(
723 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
724 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
726 $s .= $n . ' ('.$tl.')';
728 $s .= wfMsg('notloggedin');
731 $rt = $wgTitle->getPrefixedURL();
732 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
734 } else { $q = "returnto={$rt}"; }
736 $s .= "\n<br />" . $this->makeKnownLink( $li,
737 wfMsg( 'login' ), $q );
739 $n = $wgUser->getName();
740 $rt = $wgTitle->getPrefixedURL();
741 $tl = $this->makeKnownLink( $wgLang->getNsText(
742 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
743 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
747 $s .= $this->makeKnownLink( $wgLang->getNsText(
748 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
749 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
750 "returnto={$rt}" ) . ' | ' .
751 $this->specialLink( 'preferences' );
753 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
759 function getSearchLink() {
760 $searchPage =& Title
::makeTitle( NS_SPECIAL
, 'Search' );
761 return $searchPage->getLocalURL();
764 function escapeSearchLink() {
765 return htmlspecialchars( $this->getSearchLink() );
768 function searchForm() {
770 $search = $wgRequest->getText( 'search' );
772 $s = '<form name="search" class="inline" method="post" action="'
773 . $this->escapeSearchLink() . "\">\n"
774 . '<input type="text" name="search" size="19" value="'
775 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
776 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" /> '
777 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
782 function topLinks() {
786 $s = $this->mainPageLink() . $sep
787 . $this->specialLink( 'recentchanges' );
789 if ( $wgOut->isArticleRelated() ) {
790 $s .= $sep . $this->editThisPage()
791 . $sep . $this->historyLink();
793 # Many people don't like this dropdown box
794 #$s .= $sep . $this->specialPagesList();
799 function bottomLinks() {
800 global $wgOut, $wgUser, $wgTitle;
804 if ( $wgOut->isArticleRelated() ) {
805 $s .= '<strong>' . $this->editThisPage() . '</strong>';
806 if ( 0 != $wgUser->getID() ) {
807 $s .= $sep . $this->watchThisPage();
809 $s .= $sep . $this->talkLink()
810 . $sep . $this->historyLink()
811 . $sep . $this->whatLinksHere()
812 . $sep . $this->watchPageLinksLink();
814 if ( $wgTitle->getNamespace() == Namespace::getUser()
815 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
818 $id=User
::idFromName($wgTitle->getText());
819 $ip=User
::isIP($wgTitle->getText());
821 if($id ||
$ip) { # both anons and non-anons have contri list
822 $s .= $sep . $this->userContribsLink();
824 if ( 0 != $wgUser->getID() ) { # show only to signed in users
825 if($id) { # can only email non-anons
826 $s .= $sep . $this->emailUserLink();
830 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
831 $s .= "\n<br />" . $this->deleteThisPage() .
832 $sep . $this->protectThisPage() .
833 $sep . $this->moveThisPage();
835 $s .= "<br />\n" . $this->otherLanguages();
840 function pageStats() {
841 global $wgOut, $wgLang, $wgArticle, $wgRequest;
842 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
844 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
845 if ( ! $wgOut->isArticle() ) { return ''; }
846 if ( isset( $oldid ) ||
isset( $diff ) ) { return ''; }
847 if ( 0 == $wgArticle->getID() ) { return ''; }
850 if ( !$wgDisableCounters ) {
851 $count = $wgLang->formatNum( $wgArticle->getCount() );
853 $s = wfMsg( 'viewcount', $count );
857 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
858 require_once("Credits.php");
859 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
861 $s .= $this->lastModified();
864 return $s . ' ' . $this->getCopyright();
867 function getCopyright() {
868 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
871 $oldid = $wgRequest->getVal( 'oldid' );
872 $diff = $wgRequest->getVal( 'diff' );
874 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
875 $msg = 'history_copyright';
881 if( $wgRightsPage ) {
882 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
883 } elseif( $wgRightsUrl ) {
884 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
889 $out .= wfMsg( $msg, $link );
893 function getCopyrightIcon() {
894 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
896 if( $wgRightsIcon ) {
897 $icon = htmlspecialchars( $wgRightsIcon );
899 $url = htmlspecialchars( $wgRightsUrl );
900 $out .= '<a href="'.$url.'">';
902 $text = htmlspecialchars( $wgRightsText );
903 $out .= "<img src=\"$icon\" alt='$text' />";
911 function getPoweredBy() {
913 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
914 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
918 function lastModified() {
919 global $wgLang, $wgArticle;
921 $timestamp = $wgArticle->getTimestamp();
923 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
924 $s = ' ' . wfMsg( 'lastmodified', $d );
931 function logoText( $align = '' ) {
932 if ( '' != $align ) { $a = " align='{$align}'"; }
935 $mp = wfMsg( 'mainpage' );
936 $titleObj = Title
::newFromText( $mp );
937 if ( is_object( $titleObj ) ) {
938 $url = $titleObj->escapeLocalURL();
943 $logourl = $this->getLogo();
944 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
948 function quickBar() {
949 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
950 global $wgDisableUploads, $wgRemoteUploads;
952 $fname = 'Skin::quickBar';
953 wfProfileIn( $fname );
955 $action = $wgRequest->getText( 'action' );
956 $wpPreview = $wgRequest->getBool( 'wpPreview' );
957 $tns=$wgTitle->getNamespace();
959 $s = "\n<div id='quickbar'>";
960 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
963 $s .= $this->mainPageLink()
964 . $sep . $this->specialLink( 'recentchanges' )
965 . $sep . $this->specialLink( 'randompage' );
966 if ($wgUser->getID()) {
967 $s.= $sep . $this->specialLink( 'watchlist' ) ;
968 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
969 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
972 // only show watchlist link if logged in
973 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
974 $s .= "\n<br /><hr class='sep' />";
975 $articleExists = $wgTitle->getArticleId();
976 if ( $wgOut->isArticle() ||
$action =='edit' ||
$action =='history' ||
$wpPreview) {
977 if($wgOut->isArticle()) {
978 $s .= '<strong>' . $this->editThisPage() . '</strong>';
979 } else { # backlink to the article in edit or history mode
980 if($articleExists){ # no backlink if no article
983 $text = wfMsg('articlepage');
986 $text = wfMsg('viewtalkpage');
989 $text = wfMsg('userpage');
992 $text = wfMsg('viewtalkpage');
995 $text = wfMsg('wikipediapage');
998 $text = wfMsg('viewtalkpage');
1001 $text = wfMsg('imagepage');
1004 $text = wfMsg('viewtalkpage');
1007 $text= wfMsg('articlepage');
1010 $link = $wgTitle->getText();
1011 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
1012 $link = $nstext . ':' . $link ;
1015 $s .= $this->makeLink( $link, $text );
1016 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
1017 # we just throw in a "New page" text to tell the user that he's in edit mode,
1018 # and to avoid messing with the separator that is prepended to the next item
1019 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
1025 if( $tns%2
&& $action!='edit' && !$wpPreview) {
1026 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit§ion=new');
1030 watching could cause problems in edit mode:
1031 if user edits article, then loads "watch this article" in background and then saves
1032 article with "Watch this article" checkbox disabled, the article is transparently
1033 unwatched. Therefore we do not show the "Watch this page" link in edit mode
1035 if ( 0 != $wgUser->getID() && $articleExists) {
1036 if($action!='edit' && $action != 'submit' )
1038 $s .= $sep . $this->watchThisPage();
1040 if ( $wgTitle->userCanEdit() )
1041 $s .= $sep . $this->moveThisPage();
1043 if ( $wgUser->isSysop() and $articleExists ) {
1044 $s .= $sep . $this->deleteThisPage() .
1045 $sep . $this->protectThisPage();
1047 $s .= $sep . $this->talkLink();
1048 if ($articleExists && $action !='history') {
1049 $s .= $sep . $this->historyLink();
1051 $s.=$sep . $this->whatLinksHere();
1053 if($wgOut->isArticleRelated()) {
1054 $s .= $sep . $this->watchPageLinksLink();
1057 if ( Namespace::getUser() == $wgTitle->getNamespace()
1058 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1061 $id=User
::idFromName($wgTitle->getText());
1062 $ip=User
::isIP($wgTitle->getText());
1065 $s .= $sep . $this->userContribsLink();
1067 if ( 0 != $wgUser->getID() ) {
1068 if($id) { # can only email real users
1069 $s .= $sep . $this->emailUserLink();
1073 $s .= "\n<br /><hr class='sep' />";
1076 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads ||
$wgRemoteUploads ) ) {
1077 $s .= $this->specialLink( 'upload' ) . $sep;
1079 $s .= $this->specialLink( 'specialpages' )
1080 . $sep . $this->bugReportsLink();
1082 global $wgSiteSupportPage;
1083 if( $wgSiteSupportPage ) {
1084 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1085 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1088 $s .= "\n<br /></div>\n";
1089 wfProfileOut( $fname );
1093 function specialPagesList() {
1094 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1095 require_once('SpecialPage.php');
1097 $pages = SpecialPage
::getPages();
1099 foreach ( $pages[''] as $name => $page ) {
1100 $a[$name] = $page->getDescription();
1102 if ( $wgUser->isSysop() )
1104 foreach ( $pages['sysop'] as $name => $page ) {
1105 $a[$name] = $page->getDescription();
1108 if ( $wgUser->isDeveloper() )
1110 foreach ( $pages['developer'] as $name => $page ) {
1111 $a[$name] = $page->getDescription() ;
1114 $go = wfMsg( 'go' );
1115 $sp = wfMsg( 'specialpages' );
1116 $spp = $wgLang->specialPage( 'Specialpages' );
1118 $s = '<form id="specialpages" method="get" class="inline" ' .
1119 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1120 $s .= "<select name=\"wpDropdown\">\n";
1121 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1123 foreach ( $a as $name => $desc ) {
1124 $p = $wgLang->specialPage( $name );
1125 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1127 $s .= "</select>\n";
1128 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1133 function mainPageLink() {
1134 $mp = wfMsg( 'mainpage' );
1135 $s = $this->makeKnownLink( $mp, $mp );
1139 function copyrightLink() {
1140 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1141 wfMsg( 'copyrightpagename' ) );
1145 function aboutLink() {
1146 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1147 wfMsg( 'aboutsite' ) );
1152 function disclaimerLink() {
1153 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1154 wfMsg( 'disclaimers' ) );
1158 function editThisPage() {
1159 global $wgOut, $wgTitle, $wgRequest;
1161 $oldid = $wgRequest->getVal( 'oldid' );
1162 $diff = $wgRequest->getVal( 'diff' );
1163 $redirect = $wgRequest->getVal( 'redirect' );
1165 if ( ! $wgOut->isArticleRelated() ) {
1166 $s = wfMsg( 'protectedpage' );
1168 $n = $wgTitle->getPrefixedText();
1169 if ( $wgTitle->userCanEdit() ) {
1170 $t = wfMsg( 'editthispage' );
1172 #$t = wfMsg( "protectedpage" );
1173 $t = wfMsg( 'viewsource' );
1177 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1178 if ( $oldid && ! isset( $diff ) ) {
1179 $oid = '&oldid='.$oldid;
1181 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1186 function deleteThisPage() {
1187 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1189 $diff = $wgRequest->getVal( 'diff' );
1190 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1191 $n = $wgTitle->getPrefixedText();
1192 $t = wfMsg( 'deletethispage' );
1194 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1201 function protectThisPage() {
1202 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1204 $diff = $wgRequest->getVal( 'diff' );
1205 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1206 $n = $wgTitle->getPrefixedText();
1208 if ( $wgTitle->isProtected() ) {
1209 $t = wfMsg( 'unprotectthispage' );
1210 $q = 'action=unprotect';
1212 $t = wfMsg( 'protectthispage' );
1213 $q = 'action=protect';
1215 $s = $this->makeKnownLink( $n, $t, $q );
1222 function watchThisPage() {
1223 global $wgUser, $wgOut, $wgTitle;
1225 if ( $wgOut->isArticleRelated() ) {
1226 $n = $wgTitle->getPrefixedText();
1228 if ( $wgTitle->userIsWatching() ) {
1229 $t = wfMsg( 'unwatchthispage' );
1230 $q = 'action=unwatch';
1232 $t = wfMsg( 'watchthispage' );
1233 $q = 'action=watch';
1235 $s = $this->makeKnownLink( $n, $t, $q );
1237 $s = wfMsg( 'notanarticle' );
1242 function moveThisPage() {
1243 global $wgTitle, $wgLang;
1245 if ( $wgTitle->userCanEdit() ) {
1246 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1247 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1248 } // no message if page is protected - would be redundant
1252 function historyLink() {
1255 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1256 wfMsg( 'history' ), 'action=history' );
1260 function whatLinksHere() {
1261 global $wgTitle, $wgLang;
1263 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1264 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1268 function userContribsLink() {
1269 global $wgTitle, $wgLang;
1271 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1272 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1276 function emailUserLink() {
1277 global $wgTitle, $wgLang;
1279 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1280 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1284 function watchPageLinksLink() {
1285 global $wgOut, $wgTitle, $wgLang;
1287 if ( ! $wgOut->isArticleRelated() ) {
1288 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1290 $s = $this->makeKnownLink( $wgLang->specialPage(
1291 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1292 'target=' . $wgTitle->getPrefixedURL() );
1297 function otherLanguages() {
1298 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1300 $a = $wgOut->getLanguageLinks();
1301 if ( 0 == count( $a ) ) {
1302 if ( !$wgUseNewInterlanguage ) return '';
1303 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1304 if ( $ns != 0 AND $ns != 1 ) return '' ;
1306 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1307 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1308 wfMsg( 'intl' ) , $x );
1311 if ( !$wgUseNewInterlanguage ) {
1312 $s = wfMsg( 'otherlanguages' ) . ': ';
1314 global $wgLanguageCode ;
1315 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1316 $x .= '&xl='.$wgLanguageCode ;
1317 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1318 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1321 $s = wfMsg( 'otherlanguages' ) . ': ';
1323 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1324 foreach( $a as $l ) {
1325 if ( ! $first ) { $s .= ' | '; }
1328 $nt = Title
::newFromText( $l );
1329 $url = $nt->getFullURL();
1330 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1332 if ( '' == $text ) { $text = $l; }
1333 $style = $this->getExternalLinkAttributes( $l, $text );
1334 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1336 if($wgLang->isRTL()) $s .= '</span>';
1340 function bugReportsLink() {
1341 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1342 wfMsg( 'bugreports' ) );
1346 function dateLink() {
1347 global $wgLinkCache;
1348 $t1 = Title
::newFromText( gmdate( 'F j' ) );
1349 $t2 = Title
::newFromText( gmdate( 'Y' ) );
1351 $wgLinkCache->suspend();
1352 $id = $t1->getArticleID();
1353 $wgLinkCache->resume();
1356 $s = $this->makeBrokenLink( $t1->getText() );
1358 $s = $this->makeKnownLink( $t1->getText() );
1362 $wgLinkCache->suspend();
1363 $id = $t2->getArticleID();
1364 $wgLinkCache->resume();
1367 $s .= $this->makeBrokenLink( $t2->getText() );
1369 $s .= $this->makeKnownLink( $t2->getText() );
1374 function talkLink() {
1375 global $wgLang, $wgTitle, $wgLinkCache;
1377 $tns = $wgTitle->getNamespace();
1378 if ( -1 == $tns ) { return ''; }
1380 $pn = $wgTitle->getText();
1381 $tp = wfMsg( 'talkpage' );
1382 if ( Namespace::isTalk( $tns ) ) {
1383 $lns = Namespace::getSubject( $tns );
1386 $text = wfMsg('articlepage');
1389 $text = wfMsg('userpage');
1392 $text = wfMsg('wikipediapage');
1395 $text = wfMsg('imagepage');
1398 $text= wfMsg('articlepage');
1402 $lns = Namespace::getTalk( $tns );
1405 $n = $wgLang->getNsText( $lns );
1406 if ( '' == $n ) { $link = $pn; }
1407 else { $link = $n.':'.$pn; }
1409 $wgLinkCache->suspend();
1410 $s = $this->makeLink( $link, $text );
1411 $wgLinkCache->resume();
1416 function commentLink() {
1417 global $wgLang, $wgTitle, $wgLinkCache;
1419 $tns = $wgTitle->getNamespace();
1420 if ( -1 == $tns ) { return ''; }
1422 $lns = ( Namespace::isTalk( $tns ) ) ?
$tns : Namespace::getTalk( $tns );
1424 # assert Namespace::isTalk( $lns )
1426 $n = $wgLang->getNsText( $lns );
1427 $pn = $wgTitle->getText();
1431 $wgLinkCache->suspend();
1432 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit§ion=new');
1433 $wgLinkCache->resume();
1439 * After all the page content is transformed into HTML, it makes
1440 * a final pass through here for things like table backgrounds.
1441 * @todo probably deprecated [AV]
1443 function transformContent( $text ) {
1448 * Note: This function MUST call getArticleID() on the link,
1449 * otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1451 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1452 wfProfileIn( 'Skin::makeLink' );
1453 $nt = Title
::newFromText( $title );
1455 $result = $this->makeLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1457 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1458 $result = $text == "" ?
$title : $text;
1461 wfProfileOut( 'Skin::makeLink' );
1465 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1466 $nt = Title
::newFromText( $title );
1468 return $this->makeKnownLinkObj( Title
::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1470 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1471 return $text == '' ?
$title : $text;
1475 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1476 $nt = Title
::newFromText( $title );
1478 return $this->makeBrokenLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1480 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1481 return $text == '' ?
$title : $text;
1485 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1486 $nt = Title
::newFromText( $title );
1488 return $this->makeStubLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1490 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1491 return $text == '' ?
$title : $text;
1496 * Pass a title object, not a title string
1498 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' ) {
1499 global $wgOut, $wgUser;
1500 $fname = 'Skin::makeLinkObj';
1504 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1506 if ( $nt->isExternal() ) {
1507 $u = $nt->getFullURL();
1508 $link = $nt->getPrefixedURL();
1509 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1510 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1513 if ( '' != $trail ) {
1514 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1519 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1520 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1521 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1522 } elseif ( ( -1 == $nt->getNamespace() ) ||
1523 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1524 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1526 if ( $this->postParseLinkColour() ) {
1528 if ( '' != $trail ) {
1529 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1535 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1536 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1537 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1539 # Work out link colour immediately
1540 $aid = $nt->getArticleID() ;
1542 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1544 $threshold = $wgUser->getOption('stubthreshold') ;
1545 if ( $threshold > 0 ) {
1546 $dbr =& wfGetDB( DB_SLAVE
);
1547 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1548 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1549 if ( $s !== false ) {
1551 if ( $s->cur_is_redirect
OR $s->cur_namespace
!= 0 ) {
1552 $size = $threshold*2 ; # Really big
1554 $dbr->freeResult( $res );
1556 $size = $threshold*2 ; # Really big
1561 if ( $size < $threshold ) {
1562 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1564 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1573 * Pass a title object, not a title string
1575 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '' ) {
1576 global $wgOut, $wgTitle, $wgInputEncoding;
1578 $fname = 'Skin::makeKnownLinkObj';
1579 wfProfileIn( $fname );
1581 if ( !is_object( $nt ) ) {
1584 $link = $nt->getPrefixedURL();
1585 # if ( '' != $section && substr($section,0,1) != "#" ) {
1588 if ( '' == $link ) {
1590 if ( '' == $text ) {
1591 $text = htmlspecialchars( $nt->getFragment() );
1594 $u = $nt->escapeLocalURL( $query );
1596 if ( '' != $nt->getFragment() ) {
1597 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1598 $replacearray = array(
1602 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1604 if ( '' == $text ) {
1605 $text = htmlspecialchars( $nt->getPrefixedText() );
1607 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1610 if ( '' != $trail ) {
1611 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1616 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1617 wfProfileOut( $fname );
1622 * Pass a title object, not a title string
1624 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1625 global $wgOut, $wgUser;
1629 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1631 $fname = 'Skin::makeBrokenLinkObj';
1632 wfProfileIn( $fname );
1634 if ( '' == $query ) {
1637 $q = 'action=edit&'.$query;
1639 $u = $nt->escapeLocalURL( $q );
1641 if ( '' == $text ) {
1642 $text = htmlspecialchars( $nt->getPrefixedText() );
1644 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
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}";
1659 wfProfileOut( $fname );
1664 * Pass a title object, not a title string
1666 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1667 global $wgOut, $wgUser;
1669 $link = $nt->getPrefixedURL();
1671 $u = $nt->escapeLocalURL( $query );
1673 if ( '' == $text ) {
1674 $text = htmlspecialchars( $nt->getPrefixedText() );
1676 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1679 if ( '' != $trail ) {
1680 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1685 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1686 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1688 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1693 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1694 $u = $nt->escapeLocalURL( $query );
1695 if ( '' == $text ) {
1696 $text = htmlspecialchars( $nt->getPrefixedText() );
1699 if ( '' != $trail ) {
1700 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1705 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1708 /* these are used extensively in SkinPHPTal, but also some other places */
1709 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1710 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1711 $this->checkTitle($title, $name);
1712 return $title->getLocalURL( $urlaction );
1714 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1715 $title = Title
::newFromText( $name );
1716 $title = $title->getTalkPage();
1717 $this->checkTitle($title, $name);
1718 return $title->getLocalURL( $urlaction );
1720 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1721 $title = Title
::newFromText( $name );
1722 $title= $title->getSubjectPage();
1723 $this->checkTitle($title, $name);
1724 return $title->getLocalURL( $urlaction );
1726 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1727 $title = Title
::newFromText( wfMsg($name) );
1728 $this->checkTitle($title, $name);
1729 return $title->getLocalURL( $urlaction );
1731 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1732 $title = Title
::newFromText( $name );
1733 $this->checkTitle($title, $name);
1734 return $title->getLocalURL( $urlaction );
1736 # this can be passed the NS number as defined in Language.php
1737 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1738 $title = Title
::makeTitleSafe( $namespace, $name );
1739 $this->checkTitle($title, $name);
1740 return $title->getLocalURL( $urlaction );
1743 /* these return an array with the 'href' and boolean 'exists' */
1744 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1745 $title = Title
::newFromText( $name );
1746 $this->checkTitle($title, $name);
1748 'href' => $title->getLocalURL( $urlaction ),
1749 'exists' => $title->getArticleID() != 0?
true:false
1752 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1753 $title = Title
::newFromText( $name );
1754 $title = $title->getTalkPage();
1755 $this->checkTitle($title, $name);
1757 'href' => $title->getLocalURL( $urlaction ),
1758 'exists' => $title->getArticleID() != 0?
true:false
1761 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1762 $title = Title
::newFromText( $name );
1763 $title= $title->getSubjectPage();
1764 $this->checkTitle($title, $name);
1766 'href' => $title->getLocalURL( $urlaction ),
1767 'exists' => $title->getArticleID() != 0?
true:false
1770 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1771 $title = Title
::newFromText( wfMsg($name) );
1772 $this->checkTitle($title, $name);
1774 'href' => $title->getLocalURL( $urlaction ),
1775 'exists' => $title->getArticleID() != 0?
true:false
1779 # make sure we have some title to operate on
1780 /*static*/ function checkTitle ( &$title, &$name ) {
1781 if(!is_object($title)) {
1782 $title = Title
::newFromText( $name );
1783 if(!is_object($title)) {
1784 $title = Title
::newFromText( '--error: link target missing--' );
1789 function fnamePart( $url ) {
1790 $basename = strrchr( $url, '/' );
1791 if ( false === $basename ) {
1794 $basename = substr( $basename, 1 );
1796 return htmlspecialchars( $basename );
1799 function makeImage( $url, $alt = '' ) {
1803 $alt = $this->fnamePart( $url );
1805 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1809 function makeImageLink( $name, $url, $alt = '' ) {
1810 $nt = Title
::makeTitleSafe( NS_IMAGE
, $name );
1811 return $this->makeImageLinkObj( $nt, $alt );
1814 function makeImageLinkObj( $nt, $alt = '' ) {
1815 global $wgLang, $wgUseImageResize;
1816 $img = Image
::newFromTitle( $nt );
1817 $url = $img->getURL();
1820 $prefix = $postfix = '';
1822 if ( $wgUseImageResize ) {
1823 # Check if the alt text is of the form "options|alt text"
1825 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1826 # * left no resizing, just left align. label is used for alt= only
1827 # * right same, but right aligned
1828 # * none same, but not aligned
1829 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1830 # * center center the image
1831 # * framed Keep original image size, no magnify-button.
1833 $part = explode( '|', $alt);
1835 $mwThumb =& MagicWord
::get( MAG_IMG_THUMBNAIL
);
1836 $mwLeft =& MagicWord
::get( MAG_IMG_LEFT
);
1837 $mwRight =& MagicWord
::get( MAG_IMG_RIGHT
);
1838 $mwNone =& MagicWord
::get( MAG_IMG_NONE
);
1839 $mwWidth =& MagicWord
::get( MAG_IMG_WIDTH
);
1840 $mwCenter =& MagicWord
::get( MAG_IMG_CENTER
);
1841 $mwFramed =& MagicWord
::get( MAG_IMG_FRAMED
);
1842 $alt = $part[count($part)-1];
1844 $height = $framed = $thumb = false;
1845 $manual_thumb = "" ;
1847 foreach( $part as $key => $val ) {
1848 $val_parts = explode ( "=" , $val , 2 ) ;
1849 $left_part = array_shift ( $val_parts ) ;
1850 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1852 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1853 # use manually specified thumbnail
1855 $manual_thumb = array_shift ( $val_parts ) ;
1856 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1857 # remember to set an alignment, don't render immediately
1859 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1860 # remember to set an alignment, don't render immediately
1862 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1863 # remember to set an alignment, don't render immediately
1865 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1866 # remember to set an alignment, don't render immediately
1868 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1869 # $match is the image width in pixels
1870 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1871 $width = intval( $m[1] );
1872 $height = intval( $m[2] );
1874 $width = intval($match);
1876 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1880 if ( 'center' == $align )
1882 $prefix = '<span style="text-align: center">';
1883 $postfix = '</span>';
1887 if ( $thumb ||
$framed ) {
1889 # Create a thumbnail. Alignment depends on language
1890 # writing direction, # right aligned for left-to-right-
1891 # languages ("Western languages"), left-aligned
1892 # for right-to-left-languages ("Semitic languages")
1894 # If thumbnail width has not been provided, it is set
1895 # here to 180 pixels
1896 if ( $align == '' ) {
1897 $align = $wgLang->isRTL() ?
'left' : 'right';
1899 if ( ! isset($width) ) {
1902 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1904 } elseif ( isset($width) ) {
1906 # Create a resized image, without the additional thumbnail
1909 if ( ( ! $height === false )
1910 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1911 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1912 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1913 $width = $img->getWidth() * $height / $img->getHeight();
1915 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1917 } # endif $wgUseImageResize
1919 if ( empty( $alt ) ) {
1920 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1922 $alt = htmlspecialchars( $alt );
1924 $u = $nt->escapeLocalURL();
1927 $s = wfMsg( 'missingimage', $img->getName() );
1928 $s .= "<br>{$alt}<br>{$url}<br>\n";
1930 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1931 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1933 if ( '' != $align ) {
1934 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1936 return str_replace("\n", ' ',$prefix.$s.$postfix);
1940 * Make HTML for a thumbnail including image, border and caption
1941 * $img is an Image object
1943 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1944 global $wgStylePath, $wgLang;
1945 # $image = Title::makeTitleSafe( NS_IMAGE, $name );
1946 $url = $img->getURL();
1948 #$label = htmlspecialchars( $label );
1949 $alt = preg_replace( '/<[^>]*>/', '', $label);
1950 $alt = htmlspecialchars( $alt );
1952 $width = $height = 0;
1953 if ( $img->exists() )
1955 $width = $img->getWidth();
1956 $height = $img->getHeight();
1958 if ( 0 == $width ||
0 == $height )
1960 $width = $height = 200;
1962 if ( $boxwidth == 0 )
1968 // Use image dimensions, don't scale
1970 $oboxwidth = $boxwidth +
2;
1971 $boxheight = $height;
1974 $h = intval( $height/($width/$boxwidth) );
1975 $oboxwidth = $boxwidth +
2;
1976 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1978 $boxwidth *= $boxheight/$h;
1982 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1985 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1987 $manual_title = Title
::makeTitleSafe( NS_IMAGE
, $manual_thumb ); #new Title ( $manual_thumb ) ;
1988 $manual_img = Image
::newFromTitle( $manual_title );
1989 $thumbUrl = $manual_img->getURL();
1990 if ( $manual_img->exists() )
1992 $width = $manual_img->getWidth();
1993 $height = $manual_img->getHeight();
1994 $boxwidth = $width ;
1995 $boxheight = $height ;
1996 $oboxwidth = $boxwidth +
2 ;
2000 $u = $img->getEscapeLocalURL();
2002 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
2003 $magnifyalign = $wgLang->isRTL() ?
'left' : 'right';
2004 $textalign = $wgLang->isRTL() ?
' style="text-align:right"' : '';
2006 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
2007 if ( $thumbUrl == '' ) {
2008 $s .= wfMsg( 'missingimage', $img->getName() );
2011 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
2012 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
2013 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
2017 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
2018 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
2019 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
2020 'width="15" height="11" alt="'.$more.'" /></a></div>';
2023 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
2024 return str_replace("\n", ' ', $s);
2027 function makeMediaLink( $name, $url, $alt = '' ) {
2028 $nt = Title
::makeTitleSafe( Namespace::getMedia(), $name );
2029 return $this->makeMediaLinkObj( $nt, $alt );
2032 function makeMediaLinkObj( $nt, $alt = '' ) {
2033 if ( ! isset( $nt ) )
2035 ### HOTFIX. Instead of breaking, return empty string.
2038 $name = $nt->getDBKey();
2039 $url = Image
::wfImageUrl( $name );
2040 if ( empty( $alt ) ) {
2041 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2044 $u = htmlspecialchars( $url );
2045 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2050 function specialLink( $name, $key = '' ) {
2053 if ( '' == $key ) { $key = strtolower( $name ); }
2054 $pn = $wgLang->ucfirst( $name );
2055 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2059 function makeExternalLink( $url, $text, $escape = true ) {
2060 $style = $this->getExternalLinkAttributes( $url, $text );
2061 $url = htmlspecialchars( $url );
2063 $text = htmlspecialchars( $text );
2065 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2068 # Called by history lists and recent changes
2071 # Returns text for the start of the tabular part of RC
2072 function beginRecentChangesList() {
2073 $this->rc_cache
= array() ;
2074 $this->rcMoveIndex
= 0;
2075 $this->rcCacheIndex
= 0 ;
2076 $this->lastdate
= '';
2077 $this->rclistOpen
= false;
2081 function beginImageHistoryList() {
2082 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2083 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2088 * Returns text for the end of RC
2089 * If enhanced RC is in use, returns pretty much all the text
2091 function endRecentChangesList() {
2092 $s = $this->recentChangesBlock() ;
2093 if( $this->rclistOpen
) {
2100 * Enhanced RC ungrouped line
2102 function recentChangesBlockLine ( $rcObj ) {
2103 global $wgStylePath, $wgLang ;
2105 # Get rc_xxxx variables
2106 extract( $rcObj->mAttribs
) ;
2107 $curIdEq = 'curid='.$rc_cur_id;
2112 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2115 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2116 $r .= ' ';
2118 # M & N (minor & new)
2119 $M = wfMsg( 'minoreditletter' );
2120 $N = wfMsg( 'newpageletter' );
2122 if ( $rc_type == RC_NEW
) {
2135 $r .= ' '.$rcObj->timestamp
.' ' ;
2139 $link = $rcObj->link
;
2140 if ( $rcObj->watched
) $link = '<strong>'.$link.'</strong>' ;
2145 $r .= $rcObj->difflink
;
2149 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2152 $r .= ') . . '.$rcObj->userlink
;
2153 $r .= $rcObj->usertalklink
;
2156 if ( $rc_comment != '' && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2157 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2158 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2168 function recentChangesBlockGroup ( $block ) {
2169 global $wgStylePath, $wgLang ;
2172 $M = wfMsg( 'minoreditletter' );
2173 $N = wfMsg( 'newpageletter' );
2175 # Collate list of users
2177 $userlinks = array () ;
2178 foreach ( $block AS $rcObj ) {
2179 $oldid = $rcObj->mAttribs
['rc_last_oldid'];
2180 if ( $rcObj->mAttribs
['rc_new'] ) $isnew = true ;
2181 $u = $rcObj->userlink
;
2182 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2186 # Sort the list and convert to text
2187 krsort ( $userlinks ) ;
2188 asort ( $userlinks ) ;
2190 foreach ( $userlinks as $userlink => $count) {
2192 if ( $count > 1 ) $text .= " ({$count}×)" ;
2193 array_push ( $users , $text ) ;
2195 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2198 $rci = 'RCI'.$this->rcCacheIndex
;
2199 $rcl = 'RCL'.$this->rcCacheIndex
;
2200 $rcm = 'RCM'.$this->rcCacheIndex
;
2201 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2202 $arrowdir = $wgLang->isRTL() ?
'l' : 'r';
2203 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2204 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2210 if ( $isnew ) $r .= $N ;
2211 else $r .= ' ' ;
2212 $r .= ' ' ; # Minor
2215 $r .= ' '.$block[0]->timestamp
.' ' ;
2219 $link = $block[0]->link
;
2220 if ( $block[0]->watched
) $link = '<strong>'.$link.'</strong>' ;
2223 $curIdEq = 'curid=' . $block[0]->mAttribs
['rc_cur_id'];
2224 if ( $block[0]->mAttribs
['rc_type'] != RC_LOG
) {
2226 $r .= ' ('.count($block).' ' ;
2227 if ( $isnew ) $r .= wfMsg('changes');
2228 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2229 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2233 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2241 $r .= '<div id="'.$rci.'" style="display:none">' ;
2242 foreach ( $block AS $rcObj ) {
2243 # Get rc_xxxx variables
2244 extract( $rcObj->mAttribs
);
2246 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2247 $r .= '<tt> ' ;
2248 if ( $rc_new ) $r .= $N ;
2249 else $r .= ' ' ;
2250 if ( $rc_minor ) $r .= $M ;
2251 else $r .= ' ' ;
2255 if ( $rc_last_oldid != 0 ) {
2256 $o = 'oldid='.$rc_last_oldid ;
2258 if ( $rc_type == RC_LOG
) {
2259 $link = $rcObj->timestamp
;
2261 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp
, "{$curIdEq}&$o" ) ;
2263 $link = '<tt>'.$link.'</tt>' ;
2267 $r .= $rcObj->curlink
;
2269 $r .= $rcObj->lastlink
;
2270 $r .= ') . . '.$rcObj->userlink
;
2271 $r .= $rcObj->usertalklink
;
2272 if ( $rc_comment != '' ) {
2273 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2274 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2280 $this->rcCacheIndex++
;
2285 * If enhanced RC is in use, this function takes the previously cached
2286 * RC lines, arranges them, and outputs the HTML
2288 function recentChangesBlock () {
2289 global $wgStylePath ;
2290 if ( count ( $this->rc_cache
) == 0 ) return '' ;
2292 foreach ( $this->rc_cache
AS $secureName => $block ) {
2293 if ( count ( $block ) < 2 ) {
2294 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2296 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2300 return '<div>'.$blockOut.'</div>' ;
2304 * Called in a loop over all displayed RC entries
2305 * Either returns the line, or caches it for later use
2307 function recentChangesLine( &$rc, $watched = false ) {
2309 $usenew = $wgUser->getOption( 'usenewrc' );
2311 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2313 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2317 function recentChangesLineOld( &$rc, $watched = false ) {
2318 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2320 # Extract DB fields into local scope
2321 extract( $rc->mAttribs
);
2322 $curIdEq = 'curid=' . $rc_cur_id;
2324 # Make date header if necessary
2325 $date = $wgLang->date( $rc_timestamp, true);
2327 if ( $date != $this->lastdate
) {
2328 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2329 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2330 $this->lastdate
= $date;
2331 $this->rclistOpen
= true;
2334 # If this edit has not yet been patrolled, make it stick out
2335 $s .= ( ! $wgUseRCPatrol ||
$rc_patrolled ) ?
'<li> ' : '<li class="not_patrolled"> ';
2337 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2339 $s .= '(' . wfMsg( 'diff' ) . ') (';
2341 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2344 # "[[x]] moved to [[y]]"
2345 $msg = ( $rc_type == RC_MOVE
) ?
'1movedto2' : '1movedto2_redir';
2346 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2347 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2348 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2350 $logtype = $matches[1];
2351 $logname = LogPage
::logName( $logtype );
2352 $s .= '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2355 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2356 $diffLink = wfMsg( 'diff' );
2358 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2359 ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2360 $rcidparam = "&rcid={$rc_id}";
2363 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2364 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2365 '', '', ' tabindex="'.$rc->counter
.'"');
2367 $s .= '('.$diffLink.') (';
2370 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2373 # M and N (minor and new)
2374 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2375 if ( $rc_type == RC_NEW
) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2378 # If it's a new article, there is no diff link, but if it hasn't been
2379 # patrolled yet, we need to give users a way to do so
2380 if ( $wgUseRCPatrol && $rc_type == RC_NEW
&& $rc_patrolled == 0 &&
2381 $wgUser->getID() != 0 && ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2382 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2384 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2387 $articleLink = '<strong>'.$articleLink.'</strong>';
2389 $s .= ' '.$articleLink;
2394 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2396 # User link (or contributions for unregistered users)
2397 if ( 0 == $rc_user ) {
2398 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2399 $rc_user_text, 'target=' . $rc_user_text );
2401 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2406 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2407 global $wgDisableAnonTalk;
2408 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2411 $utns=$wgLang->getNsText(NS_USER_TALK
);
2412 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2416 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2417 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2418 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2422 if($userTalkLink) $userTalkLink .= ' | ';
2423 $userTalkLink .= $blockLink;
2425 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2428 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2429 $rc_comment=$this->formatComment($rc_comment,$rc->getTitle());
2430 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2437 function recentChangesLineNew( &$baseRC, $watched = false ) {
2438 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2440 # Create a specialised object
2441 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2443 # Extract fields from DB into the function scope (rc_xxxx variables)
2444 extract( $rc->mAttribs
);
2445 $curIdEq = 'curid=' . $rc_cur_id;
2447 # If it's a new day, add the headline and flush the cache
2448 $date = $wgLang->date( $rc_timestamp, true);
2450 if ( $date != $this->lastdate
) {
2451 # Process current cache
2452 $ret = $this->recentChangesBlock () ;
2453 $this->rc_cache
= array() ;
2454 $ret .= "<h4>{$date}</h4>\n";
2455 $this->lastdate
= $date;
2459 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2460 $msg = ( $rc_type == RC_MOVE
) ?
"1movedto2" : "1movedto2_redir";
2461 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2462 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2463 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2465 $logtype = $matches[1];
2466 $logname = LogPage
::logName( $logtype );
2467 $clink = '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2469 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2472 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2473 $rc->watched
= $watched ;
2474 $rc->link
= $clink ;
2475 $rc->timestamp
= $time;
2477 # Make "cur" and "diff" links
2478 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2479 $curLink = wfMsg( 'cur' );
2480 $diffLink = wfMsg( 'diff' );
2482 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2483 $aprops = ' tabindex="'.$baseRC->counter
.'"';
2484 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2485 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2489 $titleObj = $rc->getTitle();
2490 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2491 $lastLink = wfMsg( 'last' );
2493 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2494 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2497 # Make user link (or user contributions for unregistered users)
2498 if ( $rc_user == 0 ) {
2499 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2500 $rc_user_text, 'target=' . $rc_user_text );
2502 $userLink = $this->makeLink( $wgLang->getNsText(
2503 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2506 $rc->userlink
= $userLink;
2507 $rc->lastlink
= $lastLink;
2508 $rc->curlink
= $curLink;
2509 $rc->difflink
= $diffLink;
2511 # Make user talk link
2512 $utns=$wgLang->getNsText(NS_USER_TALK
);
2513 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2514 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2516 global $wgDisableAnonTalk;
2517 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2518 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2519 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2520 if( $wgDisableAnonTalk )
2521 $rc->usertalklink
= ' ('.$blockLink.')';
2523 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2525 if( $wgDisableAnonTalk && ($rc_user == 0) )
2526 $rc->usertalklink
= '';
2528 $rc->usertalklink
= ' ('.$userTalkLink.')';
2531 # Put accumulated information into the cache, for later display
2532 # Page moves go on their own line
2533 $title = $rc->getTitle();
2534 $secureName = $title->getPrefixedDBkey();
2535 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2536 # Use an @ character to prevent collision with page names
2537 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2539 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2540 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2545 function endImageHistoryList() {
2551 * This function is called by all recent changes variants, by the page history,
2552 * and by the user contributions list. It is responsible for formatting edit
2553 * comments. It escapes any HTML in the comment, but adds some CSS to format
2554 * auto-generated comments (from section editing) and formats [[wikilinks]].
2556 * The &$title parameter must be a title OBJECT. It is used to generate a
2557 * direct link to the section in the autocomment.
2558 * @author Erik Moeller <moeller@scireview.de>
2560 * Note: there's not always a title to pass to this function.
2561 * Since you can't set a default parameter for a reference, I've turned it
2562 * temporarily to a value pass. Should be adjusted further. --brion
2564 function formatComment($comment, $title = NULL) {
2566 $comment = htmlspecialchars( $comment );
2568 # The pattern for autogen comments is / * foo * /, which makes for
2570 # We look for all comments, match any text before and after the comment,
2571 # add a separator where needed and format the comment itself with CSS
2572 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2580 # This is hackish but should work in most cases.
2581 $section=str_replace('[[','',$section);
2582 $section=str_replace(']]','',$section);
2583 $title->mFragment
=$section;
2584 $link=$this->makeKnownLinkObj($title,wfMsg('sectionlink'));
2588 if($pre) { $auto = $sep.' '.$auto; }
2589 if($post) { $auto .= ' '.$sep; }
2590 $auto='<span class="autocomment">'.$auto.'</span>';
2591 $comment=$pre.$auto.$post;
2594 # format regular and media links - all other wiki formatting
2596 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2597 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2598 # Handle link renaming [[foo|text]] will show link as "text"
2599 if( "" != $match[3] ) {
2604 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2605 # Media link; trail not supported.
2606 $linkRegexp = '/\[\[(.*?)\]\]/';
2607 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2609 # Other kind of link
2610 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2611 $trail = $submatch[1];
2615 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2616 if ($match[1][0] == ':')
2617 $match[1] = substr($match[1], 1);
2618 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2620 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2625 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description ) {
2626 global $wgUser, $wgLang, $wgTitle;
2628 $datetime = $wgLang->timeanddate( $timestamp, true );
2629 $del = wfMsg( 'deleteimg' );
2630 $delall = wfMsg( 'deleteimgcompletely' );
2631 $cur = wfMsg( 'cur' );
2634 $url = Image
::wfImageUrl( $img );
2636 if ( $wgUser->isSysop() ) {
2637 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2639 $style = $this->getInternalLinkAttributes( $link, $delall );
2641 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2646 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2647 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2648 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2649 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2650 urlencode( $img ) );
2651 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2652 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2654 # Having live active links for non-logged in users
2655 # means that bots and spiders crawling our site can
2656 # inadvertently change content. Baaaad idea.
2657 $rlink = wfMsg( 'revertimg' );
2662 $userlink = $usertext;
2664 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2665 ':'.$usertext, $usertext );
2667 $nbytes = wfMsg( 'nbytes', $size );
2668 $style = $this->getInternalLinkAttributes( $url, $datetime );
2670 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2671 . " . . {$userlink} ({$nbytes})";
2673 if ( '' != $description && '*' != $description ) {
2674 $sk=$wgUser->getSkin();
2675 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description,$wgTitle) . ')');
2681 function tocIndent($level) {
2682 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2685 function tocUnindent($level) {
2686 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2690 * parameter level defines if we are on an indentation level
2692 function tocLine( $anchor, $tocline, $level ) {
2693 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2697 return '<div class="tocline">'.$link."</div>\n";
2702 function tocTable($toc) {
2703 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2704 # try min-width & co when somebody gets a chance
2705 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2707 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2708 '<b>'.wfMsg('toc').'</b>' .
2710 '</td></tr><tr id="tocinside"><td>'."\n".
2711 $toc."</td></tr></table>\n";
2715 * These two do not check for permissions: check $wgTitle->userCanEdit
2716 * before calling them
2718 function editSectionScript( $section, $head ) {
2719 global $wgTitle, $wgRequest;
2720 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2723 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2724 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2727 function editSectionLink( $section ) {
2729 global $wgTitle, $wgUser, $wgLang;
2731 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2732 # Section edit links would be out of sync on an old page.
2733 # But, if we're diffing to the current page, they'll be
2738 $editurl = '§ion='.$section;
2739 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2741 if( $wgLang->isRTL() ) {
2743 $nearside = 'right';
2748 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2753 * This function is called by EditPage.php and shows a bulletin board style
2754 * toolbar for common editing functions. It can be disabled in the user
2756 * The necsesary JavaScript code can be found in style/wikibits.js.
2758 function getEditToolbar() {
2759 global $wgStylePath, $wgLang, $wgMimeType;
2762 * toolarray an array of arrays which each include the filename of
2763 * the button image (without path), the opening tag, the closing tag,
2764 * and optionally a sample text that is inserted between the two when no
2765 * selection is highlighted.
2766 * The tip text is shown when the user moves the mouse over the button.
2768 * Already here are accesskeys (key), which are not used yet until someone
2769 * can figure out a way to make them work in IE. However, we should make
2770 * sure these keys are not defined on the edit page.
2773 array( 'image'=>'button_bold.png',
2775 'close' => "\'\'\'",
2776 'sample'=> wfMsg('bold_sample'),
2777 'tip' => wfMsg('bold_tip'),
2780 array( 'image'=>'button_italic.png',
2783 'sample'=> wfMsg('italic_sample'),
2784 'tip' => wfMsg('italic_tip'),
2787 array( 'image'=>'button_link.png',
2790 'sample'=> wfMsg('link_sample'),
2791 'tip' => wfMsg('link_tip'),
2794 array( 'image'=>'button_extlink.png',
2797 'sample'=> wfMsg('extlink_sample'),
2798 'tip' => wfMsg('extlink_tip'),
2801 array( 'image'=>'button_headline.png',
2803 'close' => " ==\\n",
2804 'sample'=> wfMsg('headline_sample'),
2805 'tip' => wfMsg('headline_tip'),
2808 array( 'image'=>'button_image.png',
2809 'open' => '[['.$wgLang->getNsText(NS_IMAGE
).":",
2811 'sample'=> wfMsg('image_sample'),
2812 'tip' => wfMsg('image_tip'),
2815 array( 'image' => 'button_media.png',
2816 'open' => '[['.$wgLang->getNsText(NS_MEDIA
).':',
2818 'sample'=> wfMsg('media_sample'),
2819 'tip' => wfMsg('media_tip'),
2822 array( 'image' => 'button_math.png',
2823 'open' => "\\<math\\>",
2824 'close' => "\\</math\\>",
2825 'sample'=> wfMsg('math_sample'),
2826 'tip' => wfMsg('math_tip'),
2829 array( 'image' => 'button_nowiki.png',
2830 'open' => "\\<nowiki\\>",
2831 'close' => "\\</nowiki\\>",
2832 'sample'=> wfMsg('nowiki_sample'),
2833 'tip' => wfMsg('nowiki_tip'),
2836 array( 'image' => 'button_sig.png',
2840 'tip' => wfMsg('sig_tip'),
2843 array( 'image' => 'button_hr.png',
2844 'open' => "\\n----\\n",
2847 'tip' => wfMsg('hr_tip'),
2851 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2853 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2854 foreach($toolarray as $tool) {
2856 $image=$wgStylePath.'/images/'.$tool['image'];
2857 $open=$tool['open'];
2858 $close=$tool['close'];
2859 $sample = addslashes( $tool['sample'] );
2861 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2862 // Older browsers show a "speedtip" type message only for ALT.
2863 // Ideally these should be different, realistically they
2864 // probably don't need to be.
2865 $tip = addslashes( $tool['tip'] );
2867 #$key = $tool["key"];
2869 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2872 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2873 $toolbar.="document.writeln(\"</div>\");\n";
2875 $toolbar.="/*]]>*/\n</script>";
2882 function suppressUrlExpansion() {