9 * This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
11 if( defined( "MEDIAWIKI" ) ) {
14 require_once( 'Image.php' );
16 # These are the INTERNAL names, which get mapped directly to class names and
17 # file names in ./skins/. For display purposes, the Language class has
18 # internationalized names
21 $wgValidSkinNames = array(
22 'standard' => 'Standard',
23 'nostalgia' => 'Nostalgia',
24 'cologneblue' => 'CologneBlue'
27 #$wgValidSkinNames[] = 'PHPTal';
28 #$wgValidSkinNames['davinci'] = 'DaVinci';
29 #$wgValidSkinNames['mono'] = 'Mono';
30 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
31 $wgValidSkinNames['monobook'] = 'MonoBook';
32 $wgValidSkinNames['myskin'] = 'MySkin';
33 $wgValidSkinNames['chick'] = 'Chick';
37 # Get a list of all skins available in /skins/
38 # Build using the regular expression '^(.*).php$'
39 # Array keys are all lower case, array value keep the case used by filename
42 $skinDir = dir($IP.'/skins');
44 # while code from www.php.net
45 while (false !== ($file = $skinDir->read())) {
46 if(preg_match('/^(.*).php$/',$file, $matches)) {
48 $wgValidSkinNames[strtolower($aSkin)] = $aSkin;
54 require_once( 'RecentChange.php' );
56 global $wgLinkHolders;
57 $wgLinkHolders = array(
58 'namespaces' => array(),
64 global $wgInterwikiLinkHolders;
65 $wgInterwikiLinkHolders = array();
71 class RCCacheEntry
extends RecentChange
73 var $secureName, $link;
74 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
75 var $userlink, $timestamp, $watched;
77 function newFromParent( $rc )
79 $rc2 = new RCCacheEntry
;
80 $rc2->mAttribs
= $rc->mAttribs
;
81 $rc2->mExtra
= $rc->mExtra
;
88 * The main skin class that provide methods and properties for all other skins
89 * including PHPTal skins.
90 * This base class is also the "Standard" skin.
97 var $lastdate, $lastline;
98 var $linktrail ; # linktrail regexp
99 var $rc_cache ; # Cache for Enhanced Recent Changes
100 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
102 var $postParseLinkColour = true;
106 global $wgUseOldExistenceCheck;
107 $postParseLinkColour = !$wgUseOldExistenceCheck;
108 $this->linktrail
= wfMsg('linktrail');
111 function getSkinNames() {
112 global $wgValidSkinNames;
113 return $wgValidSkinNames;
116 function getStylesheet() {
117 return 'common/wikistandard.css';
120 function getSkinName() {
125 * Get/set accessor for delayed link colouring
127 function postParseLinkColour( $setting = NULL ) {
128 return wfSetVar( $this->postParseLinkColour
, $setting );
131 function qbSetting() {
132 global $wgOut, $wgUser;
134 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
135 $q = $wgUser->getOption( 'quickbar' );
136 if ( '' == $q ) { $q = 0; }
140 function initPage( &$out ) {
141 $fname = 'Skin::initPage';
142 wfProfileIn( $fname );
144 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
146 $this->addMetadataLinks($out);
148 wfProfileOut( $fname );
151 function addMetadataLinks( &$out ) {
152 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
153 global $wgRightsPage, $wgRightsUrl;
155 if( $out->isArticleRelated() ) {
156 # note: buggy CC software only reads first "meta" link
157 if( $wgEnableCreativeCommonsRdf ) {
158 $out->addMetadataLink( array(
159 'title' => 'Creative Commons',
160 'type' => 'application/rdf+xml',
161 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
163 if( $wgEnableDublinCoreRdf ) {
164 $out->addMetadataLink( array(
165 'title' => 'Dublin Core',
166 'type' => 'application/rdf+xml',
167 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
171 if( $wgRightsPage ) {
172 $copy = Title
::newFromText( $wgRightsPage );
174 $copyright = $copy->getLocalURL();
177 if( !$copyright && $wgRightsUrl ) {
178 $copyright = $wgRightsUrl;
181 $out->addLink( array(
182 'rel' => 'copyright',
183 'href' => $copyright ) );
187 function outputPage( &$out ) {
188 global $wgDebugComments;
190 wfProfileIn( 'Skin::outputPage' );
191 $this->initPage( $out );
192 $out->out( $out->headElement() );
194 $out->out( "\n<body" );
195 $ops = $this->getBodyOptions();
196 foreach ( $ops as $name => $val ) {
197 $out->out( " $name='$val'" );
200 if ( $wgDebugComments ) {
201 $out->out( "<!-- Wiki debugging output:\n" .
202 $out->mDebugtext
. "-->\n" );
204 $out->out( $this->beforeContent() );
206 $out->out( $out->mBodytext
. "\n" );
208 $out->out( $this->afterContent() );
211 $out->out( $out->reportTime() );
213 $out->out( "\n</body></html>" );
216 function getHeadScripts() {
217 global $wgStylePath, $wgUser, $wgContLang, $wgAllowUserJs;
218 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/common/wikibits.js\"></script>\n";
219 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
220 $userpage = $wgContLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
221 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
222 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
227 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
228 function getUserStylesheet() {
229 global $wgOut, $wgStylePath, $wgContLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
230 $sheet = $this->getStylesheet();
231 $action = $wgRequest->getText('action');
232 $s = "@import \"$wgStylePath/$sheet\";\n";
233 if($wgContLang->isRTL()) $s .= "@import \"$wgStylePath/common/common_rtl.css\";\n";
234 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
235 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
236 $s .= $wgRequest->getText('wpTextbox1');
238 $userpage = $wgContLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
239 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
242 $s .= $this->doGetUserStyles();
247 * placeholder, returns generated js in monobook
249 function getUserJs() { return; }
252 * Return html code that include User stylesheets
254 function getUserStyles() {
255 global $wgOut, $wgStylePath, $wgLang;
256 $s = "<style type='text/css'>\n";
257 $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
258 $s .= $this->getUserStylesheet();
259 $s .= "/*]]>*/ /* */\n";
265 * Some styles that are set by user through the user settings interface.
267 function doGetUserStyles() {
268 global $wgUser, $wgContLang;
270 $csspage = $wgContLang->getNsText( NS_MEDIAWIKI
) . ':' . $this->getSkinName() . '.css';
271 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
273 if ( 1 == $wgUser->getOption( 'underline' ) ) {
274 # Don't override browser settings
278 $s .= "a { text-decoration: none; }\n";
280 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
281 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
283 if ( 1 == $wgUser->getOption( 'justify' ) ) {
284 $s .= "#article { text-align: justify; }\n";
289 function getBodyOptions() {
290 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
292 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
294 if ( 0 != $wgTitle->getNamespace() ) {
295 $a = array( 'bgcolor' => '#ffffec' );
297 else $a = array( 'bgcolor' => '#FFFFFF' );
298 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
299 (!$wgTitle->isProtected() ||
$wgUser->isSysop()) ) {
300 $t = wfMsg( 'editthispage' );
302 if ( !empty($redirect) ) {
303 $red = "&redirect={$redirect}";
305 if ( !empty($oldid) && ! isset( $diff ) ) {
306 $oid = "&oldid={$oldid}";
308 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
309 $s = 'document.location = "' .$s .'";';
310 $a +
= array ('ondblclick' => $s);
313 $a['onload'] = $wgOut->getOnloadHandler();
317 function getExternalLinkAttributes( $link, $text, $class='' ) {
318 global $wgUser, $wgOut, $wgContLang;
320 $same = ($link == $text);
321 $link = urldecode( $link );
322 $link = $wgContLang->checkTitleEncoding( $link );
323 $link = str_replace( '_', ' ', $link );
324 $link = htmlspecialchars( $link );
326 $r = ($class != '') ?
" class='$class'" : " class='external'";
328 if ( !$same && $wgUser->getOption( 'hover' ) ) {
329 $r .= " title=\"{$link}\"";
334 function getInternalLinkAttributes( $link, $text, $broken = false ) {
335 global $wgUser, $wgOut;
337 $link = urldecode( $link );
338 $link = str_replace( '_', ' ', $link );
339 $link = htmlspecialchars( $link );
341 if ( $broken == 'stub' ) {
342 $r = ' class="stub"';
343 } else if ( $broken == 'yes' ) {
349 if ( 1 == $wgUser->getOption( 'hover' ) ) {
350 $r .= " title=\"{$link}\"";
356 * @param bool $broken
358 function getInternalLinkAttributesObj( &$nt, $text, $broken = false ) {
359 global $wgUser, $wgOut;
361 if ( $broken == 'stub' ) {
362 $r = ' class="stub"';
363 } else if ( $broken == 'yes' ) {
369 if ( 1 == $wgUser->getOption( 'hover' ) ) {
370 $r .= ' title="' . $nt->getEscapedText() . '"';
384 * This will be called immediately after the <body> tag. Split into
385 * two functions to make it easier to subclass.
387 function beforeContent() {
388 global $wgUser, $wgOut;
390 return $this->doBeforeContent();
393 function doBeforeContent() {
394 global $wgUser, $wgOut, $wgTitle, $wgContLang, $wgSiteNotice;
395 $fname = 'Skin::doBeforeContent';
396 wfProfileIn( $fname );
399 $qb = $this->qbSetting();
401 if( $langlinks = $this->otherLanguages() ) {
407 $borderhack = 'class="top"';
410 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
411 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
414 $left = ($qb == 1 ||
$qb == 3);
415 if($wgContLang->isRTL()) $left = !$left;
418 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
419 $this->logoText() . '</td>';
421 $s .= $this->getQuickbarCompensator( $rows );
423 $l = $wgContLang->isRTL() ?
'right' : 'left';
424 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
426 $s .= $this->topLinks() ;
427 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
429 $r = $wgContLang->isRTL() ?
"left" : "right";
430 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
431 $s .= $this->nameAndLogin();
432 $s .= "\n<br />" . $this->searchForm() . "</td>";
435 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
438 if ( $shove && !$left ) { # Right
439 $s .= $this->getQuickbarCompensator( $rows );
441 $s .= "</tr>\n</table>\n</div>\n";
442 $s .= "\n<div id='article'>\n";
444 if( $wgSiteNotice ) {
445 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
447 $s .= $this->pageTitle();
448 $s .= $this->pageSubtitle() ;
449 $s .= $this->getCategories();
450 wfProfileOut( $fname );
454 function getCategoryLinks () {
455 global $wgOut, $wgTitle, $wgUser, $wgParser;
456 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
458 if( !$wgUseCategoryMagic ) return '' ;
459 if( count( $wgOut->mCategoryLinks
) == 0 ) return '';
461 # Taken out so that they will be displayed in previews -- TS
462 #if( !$wgOut->isArticle() ) return '';
464 $t = implode ( ' | ' , $wgOut->mCategoryLinks
) ;
465 $s = $this->makeKnownLink( 'Special:Categories',
466 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
469 # optional 'dmoz-like' category browser. Will be shown under the list
470 # of categories an article belong to
471 if($wgUseCategoryBrowser) {
474 # get a big array of the parents tree
475 $parenttree = $wgTitle->getCategorieBrowser();
477 # Render the array as a serie of links
478 function walkThrough ($tree) {
480 $sk = $wgUser->getSkin();
482 foreach($tree as $element => $parent) {
484 # element start a new list
487 # grab the others elements
488 $return .= walkThrough($parent);
490 # add our current element to the list
491 $eltitle = Title
::NewFromText($element);
492 # FIXME : should be makeLink() [AV]
493 $return .= $sk->makeKnownLink($element, $eltitle->getText()).' > ';
498 $s .= walkThrough($parenttree);
504 function getCategories() {
505 $catlinks=$this->getCategoryLinks();
506 if(!empty($catlinks)) {
507 return "<p class='catlinks'>{$catlinks}</p>";
511 function getQuickbarCompensator( $rows = 1 ) {
512 return "<td width='152' rowspan='{$rows}'> </td>";
515 # This gets called immediately before the </body> tag.
517 function afterContent() {
518 global $wgUser, $wgOut, $wgServer;
519 global $wgTitle, $wgLang;
521 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
522 return $printfooter . $this->doAfterContent();
525 function printSource() {
527 $url = htmlspecialchars( $wgTitle->getFullURL() );
528 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
531 function printFooter() {
532 return "<p>" . $this->printSource() .
533 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
536 function doAfterContent() {
537 # overloaded by derived classes
540 function pageTitleLinks() {
541 global $wgOut, $wgTitle, $wgUser, $wgContLang, $wgUseApproval, $wgRequest;
543 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
544 $action = $wgRequest->getText( 'action' );
546 $s = $this->printableLink();
547 if ( wfMsgForContent ( 'disclaimers' ) != '-' )
548 $s .= ' | ' . $this->makeKnownLink(
549 wfMsgForContent( 'disclaimerpage' ),
550 wfMsgForContent( 'disclaimers' ) ) ;
552 if ( $wgOut->isArticleRelated() ) {
553 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
554 $name = $wgTitle->getDBkey();
555 $link = htmlspecialchars( Image
::wfImageUrl( $name ) );
556 $style = $this->getInternalLinkAttributes( $link, $name );
557 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
559 # This will show the "Approve" link if $wgUseApproval=true;
560 if ( isset ( $wgUseApproval ) && $wgUseApproval )
562 $t = $wgTitle->getDBkey();
563 $name = 'Approve this article' ;
564 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
565 #htmlspecialchars( wfImageUrl( $name ) );
566 $style = $this->getExternalLinkAttributes( $link, $name );
567 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
570 if ( 'history' == $action ||
isset( $diff ) ||
isset( $oldid ) ) {
571 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
572 wfMsg( 'currentrev' ) );
575 if ( $wgUser->getNewtalk() ) {
576 # do not show "You have new messages" text when we are viewing our
579 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
580 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
581 $n =$wgUser->getName();
582 $tl = $this->makeKnownLink( $wgContLang->getNsText(
583 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
584 wfMsg('newmessageslink') );
585 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
587 $wgOut->setSquidMaxage(0);
591 $undelete = $this->getUndeleteLink();
592 if( !empty( $undelete ) ) {
593 $s .= ' | '.$undelete;
598 function getUndeleteLink() {
599 global $wgUser, $wgTitle, $wgContLang, $action;
600 if( $wgUser->isSysop() &&
601 (($wgTitle->getArticleId() == 0) ||
($action == "history")) &&
602 ($n = $wgTitle->isDeleted() ) ) {
603 return wfMsg( 'thisisdeleted',
604 $this->makeKnownLink(
605 $wgContLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
606 wfMsg( 'restorelink', $n ) ) );
611 function printableLink() {
612 global $wgOut, $wgFeedClasses, $wgRequest;
614 $baseurl = $_SERVER['REQUEST_URI'];
615 if( strpos( '?', $baseurl ) == false ) {
620 $baseurl = htmlspecialchars( $baseurl );
621 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
623 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
624 if( $wgOut->isSyndicated() ) {
625 foreach( $wgFeedClasses as $format => $class ) {
626 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
627 $s .= " | <a href=\"$feedurl\">{$format}</a>";
633 function pageTitle() {
634 global $wgOut, $wgTitle, $wgUser;
636 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
637 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
641 function pageSubtitle() {
644 $sub = $wgOut->getSubtitle();
646 global $wgExtraSubtitle;
647 $sub = wfMsg( 'tagline' ) . $wgExtraSubtitle;
649 $subpages = $this->subPageSubtitle();
650 $sub .= !empty($subpages)?
"</p><p class='subpages'>$subpages":'';
651 $s = "<p class='subtitle'>{$sub}</p>\n";
655 function subPageSubtitle() {
656 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
658 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
659 $ptext=$wgTitle->getPrefixedText();
660 if(preg_match('/\//',$ptext)) {
661 $links = explode('/',$ptext);
664 foreach($links as $link) {
666 if ($c<count($links)) {
667 $growinglink .= $link;
668 $getlink = $this->makeLink( $growinglink, $link );
669 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
673 $subpages .= '< ';
675 $subpages .= $getlink;
684 function nameAndLogin() {
685 global $wgUser, $wgTitle, $wgLang, $wgContLang, $wgShowIPinHeader, $wgIP;
687 $li = $wgContLang->specialPage( 'Userlogin' );
688 $lo = $wgContLang->specialPage( 'Userlogout' );
691 if ( 0 == $wgUser->getID() ) {
692 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
695 $tl = $this->makeKnownLink( $wgContLang->getNsText(
696 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
697 $wgContLang->getNsText( Namespace::getTalk( 0 ) ) );
699 $s .= $n . ' ('.$tl.')';
701 $s .= wfMsg('notloggedin');
704 $rt = $wgTitle->getPrefixedURL();
705 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
707 } else { $q = "returnto={$rt}"; }
709 $s .= "\n<br />" . $this->makeKnownLink( $li,
710 wfMsg( 'login' ), $q );
712 $n = $wgUser->getName();
713 $rt = $wgTitle->getPrefixedURL();
714 $tl = $this->makeKnownLink( $wgContLang->getNsText(
715 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
716 $wgContLang->getNsText( Namespace::getTalk( 0 ) ) );
720 $s .= $this->makeKnownLink( $wgContLang->getNsText(
721 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
722 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
723 "returnto={$rt}" ) . ' | ' .
724 $this->specialLink( 'preferences' );
726 $s .= ' | ' . $this->makeKnownLink( wfMsgForContent( 'helppage' ),
732 function getSearchLink() {
733 $searchPage =& Title
::makeTitle( NS_SPECIAL
, 'Search' );
734 return $searchPage->getLocalURL();
737 function escapeSearchLink() {
738 return htmlspecialchars( $this->getSearchLink() );
741 function searchForm() {
743 $search = $wgRequest->getText( 'search' );
745 $s = '<form name="search" class="inline" method="post" action="'
746 . $this->escapeSearchLink() . "\">\n"
747 . '<input type="text" name="search" size="19" value="'
748 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
749 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" /> '
750 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
755 function topLinks() {
759 $s = $this->mainPageLink() . $sep
760 . $this->specialLink( 'recentchanges' );
762 if ( $wgOut->isArticleRelated() ) {
763 $s .= $sep . $this->editThisPage()
764 . $sep . $this->historyLink();
766 # Many people don't like this dropdown box
767 #$s .= $sep . $this->specialPagesList();
772 function bottomLinks() {
773 global $wgOut, $wgUser, $wgTitle;
777 if ( $wgOut->isArticleRelated() ) {
778 $s .= '<strong>' . $this->editThisPage() . '</strong>';
779 if ( 0 != $wgUser->getID() ) {
780 $s .= $sep . $this->watchThisPage();
782 $s .= $sep . $this->talkLink()
783 . $sep . $this->historyLink()
784 . $sep . $this->whatLinksHere()
785 . $sep . $this->watchPageLinksLink();
787 if ( $wgTitle->getNamespace() == Namespace::getUser()
788 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
791 $id=User
::idFromName($wgTitle->getText());
792 $ip=User
::isIP($wgTitle->getText());
794 if($id ||
$ip) { # both anons and non-anons have contri list
795 $s .= $sep . $this->userContribsLink();
797 if ( 0 != $wgUser->getID() ) { # show only to signed in users
798 if($id) { # can only email non-anons
799 $s .= $sep . $this->emailUserLink();
803 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
804 $s .= "\n<br />" . $this->deleteThisPage() .
805 $sep . $this->protectThisPage() .
806 $sep . $this->moveThisPage();
808 $s .= "<br />\n" . $this->otherLanguages();
813 function pageStats() {
814 global $wgOut, $wgLang, $wgArticle, $wgRequest;
815 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
817 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
818 if ( ! $wgOut->isArticle() ) { return ''; }
819 if ( isset( $oldid ) ||
isset( $diff ) ) { return ''; }
820 if ( 0 == $wgArticle->getID() ) { return ''; }
823 if ( !$wgDisableCounters ) {
824 $count = $wgLang->formatNum( $wgArticle->getCount() );
826 $s = wfMsg( 'viewcount', $count );
830 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
831 require_once("Credits.php");
832 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
834 $s .= $this->lastModified();
837 return $s . ' ' . $this->getCopyright();
840 function getCopyright() {
841 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
844 $oldid = $wgRequest->getVal( 'oldid' );
845 $diff = $wgRequest->getVal( 'diff' );
847 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsgForContent( 'history_copyright' ) !== '-' ) {
848 $msg = 'history_copyright';
854 if( $wgRightsPage ) {
855 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
856 } elseif( $wgRightsUrl ) {
857 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
862 $out .= wfMsgForContent( $msg, $link );
866 function getCopyrightIcon() {
867 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
869 if( $wgRightsIcon ) {
870 $icon = htmlspecialchars( $wgRightsIcon );
872 $url = htmlspecialchars( $wgRightsUrl );
873 $out .= '<a href="'.$url.'">';
875 $text = htmlspecialchars( $wgRightsText );
876 $out .= "<img src=\"$icon\" alt='$text' />";
884 function getPoweredBy() {
886 $url = htmlspecialchars( "$wgStylePath/common/images/poweredby_mediawiki_88x31.png" );
887 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
891 function lastModified() {
892 global $wgLang, $wgArticle;
894 $timestamp = $wgArticle->getTimestamp();
896 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
897 $s = ' ' . wfMsg( 'lastmodified', $d );
904 function logoText( $align = '' ) {
905 if ( '' != $align ) { $a = " align='{$align}'"; }
908 $mp = wfMsg( 'mainpage' );
909 $titleObj = Title
::newFromText( $mp );
910 if ( is_object( $titleObj ) ) {
911 $url = $titleObj->escapeLocalURL();
916 $logourl = $this->getLogo();
917 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
921 function quickBar() {
922 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgContLang;
923 global $wgDisableUploads, $wgRemoteUploads;
925 $fname = 'Skin::quickBar';
926 wfProfileIn( $fname );
928 $action = $wgRequest->getText( 'action' );
929 $wpPreview = $wgRequest->getBool( 'wpPreview' );
930 $tns=$wgTitle->getNamespace();
932 $s = "\n<div id='quickbar'>";
933 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
936 $s .= $this->mainPageLink()
937 . $sep . $this->specialLink( 'recentchanges' )
938 . $sep . $this->specialLink( 'randompage' );
939 if ($wgUser->getID()) {
940 $s.= $sep . $this->specialLink( 'watchlist' ) ;
941 $s .= $sep .$this->makeKnownLink( $wgContLang->specialPage( 'Contributions' ),
942 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
945 // only show watchlist link if logged in
946 if ( wfMsgForContent ( 'currentevents' ) != '-' )
947 $s .= $sep . $this->makeKnownLink( wfMsgForContent( 'currentevents' ), '' ) ;
948 $s .= "\n<br /><hr class='sep' />";
949 $articleExists = $wgTitle->getArticleId();
950 if ( $wgOut->isArticle() ||
$action =='edit' ||
$action =='history' ||
$wpPreview) {
951 if($wgOut->isArticle()) {
952 $s .= '<strong>' . $this->editThisPage() . '</strong>';
953 } else { # backlink to the article in edit or history mode
954 if($articleExists){ # no backlink if no article
957 $text = wfMsg('articlepage');
960 $text = wfMsg('viewtalkpage');
963 $text = wfMsg('userpage');
966 $text = wfMsg('viewtalkpage');
969 $text = wfMsg('wikipediapage');
972 $text = wfMsg('viewtalkpage');
975 $text = wfMsg('imagepage');
978 $text = wfMsg('viewtalkpage');
981 $text= wfMsg('articlepage');
984 $link = $wgTitle->getText();
985 if ($nstext = $wgContLang->getNsText($tns) ) { # add namespace if necessary
986 $link = $nstext . ':' . $link ;
989 $s .= $this->makeLink( $link, $text );
990 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
991 # we just throw in a "New page" text to tell the user that he's in edit mode,
992 # and to avoid messing with the separator that is prepended to the next item
993 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
999 if( $tns%2
&& $action!='edit' && !$wpPreview) {
1000 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit§ion=new');
1004 watching could cause problems in edit mode:
1005 if user edits article, then loads "watch this article" in background and then saves
1006 article with "Watch this article" checkbox disabled, the article is transparently
1007 unwatched. Therefore we do not show the "Watch this page" link in edit mode
1009 if ( 0 != $wgUser->getID() && $articleExists) {
1010 if($action!='edit' && $action != 'submit' )
1012 $s .= $sep . $this->watchThisPage();
1014 if ( $wgTitle->userCanEdit() )
1015 $s .= $sep . $this->moveThisPage();
1017 if ( $wgUser->isSysop() and $articleExists ) {
1018 $s .= $sep . $this->deleteThisPage() .
1019 $sep . $this->protectThisPage();
1021 $s .= $sep . $this->talkLink();
1022 if ($articleExists && $action !='history') {
1023 $s .= $sep . $this->historyLink();
1025 $s.=$sep . $this->whatLinksHere();
1027 if($wgOut->isArticleRelated()) {
1028 $s .= $sep . $this->watchPageLinksLink();
1031 if ( Namespace::getUser() == $wgTitle->getNamespace()
1032 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1035 $id=User
::idFromName($wgTitle->getText());
1036 $ip=User
::isIP($wgTitle->getText());
1039 $s .= $sep . $this->userContribsLink();
1041 if ( 0 != $wgUser->getID() ) {
1042 if($id) { # can only email real users
1043 $s .= $sep . $this->emailUserLink();
1047 $s .= "\n<br /><hr class='sep' />";
1050 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads ||
$wgRemoteUploads ) ) {
1051 $s .= $this->specialLink( 'upload' ) . $sep;
1053 $s .= $this->specialLink( 'specialpages' )
1054 . $sep . $this->bugReportsLink();
1056 global $wgSiteSupportPage;
1057 if( $wgSiteSupportPage ) {
1058 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1059 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1062 $s .= "\n<br /></div>\n";
1063 wfProfileOut( $fname );
1067 function specialPagesList() {
1068 global $wgUser, $wgOut, $wgContLang, $wgServer, $wgRedirectScript;
1069 require_once('SpecialPage.php');
1071 $pages = SpecialPage
::getPages();
1073 foreach ( $pages[''] as $name => $page ) {
1074 $a[$name] = $page->getDescription();
1076 if ( $wgUser->isSysop() )
1078 foreach ( $pages['sysop'] as $name => $page ) {
1079 $a[$name] = $page->getDescription();
1082 if ( $wgUser->isDeveloper() )
1084 foreach ( $pages['developer'] as $name => $page ) {
1085 $a[$name] = $page->getDescription() ;
1088 $go = wfMsg( 'go' );
1089 $sp = wfMsg( 'specialpages' );
1090 $spp = $wgContLang->specialPage( 'Specialpages' );
1092 $s = '<form id="specialpages" method="get" class="inline" ' .
1093 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1094 $s .= "<select name=\"wpDropdown\">\n";
1095 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1097 foreach ( $a as $name => $desc ) {
1098 $p = $wgContLang->specialPage( $name );
1099 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1101 $s .= "</select>\n";
1102 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1107 function mainPageLink() {
1108 $mp = wfMsgForContent( 'mainpage' );
1109 $mptxt = wfMsg( 'mainpage');
1110 $s = $this->makeKnownLink( $mp, $mptxt );
1114 function copyrightLink() {
1115 $s = $this->makeKnownLink( wfMsgForContent( 'copyrightpage' ),
1116 wfMsg( 'copyrightpagename' ) );
1120 function aboutLink() {
1121 $s = $this->makeKnownLink( wfMsgForContent( 'aboutpage' ),
1122 wfMsg( 'aboutsite' ) );
1127 function disclaimerLink() {
1128 $s = $this->makeKnownLink( wfMsgForContent( 'disclaimerpage' ),
1129 wfMsg( 'disclaimers' ) );
1133 function editThisPage() {
1134 global $wgOut, $wgTitle, $wgRequest;
1136 $oldid = $wgRequest->getVal( 'oldid' );
1137 $diff = $wgRequest->getVal( 'diff' );
1138 $redirect = $wgRequest->getVal( 'redirect' );
1140 if ( ! $wgOut->isArticleRelated() ) {
1141 $s = wfMsg( 'protectedpage' );
1143 $n = $wgTitle->getPrefixedText();
1144 if ( $wgTitle->userCanEdit() ) {
1145 $t = wfMsg( 'editthispage' );
1147 #$t = wfMsg( "protectedpage" );
1148 $t = wfMsg( 'viewsource' );
1152 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1153 if ( $oldid && ! isset( $diff ) ) {
1154 $oid = '&oldid='.$oldid;
1156 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1161 function deleteThisPage() {
1162 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1164 $diff = $wgRequest->getVal( 'diff' );
1165 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1166 $n = $wgTitle->getPrefixedText();
1167 $t = wfMsg( 'deletethispage' );
1169 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1176 function protectThisPage() {
1177 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1179 $diff = $wgRequest->getVal( 'diff' );
1180 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1181 $n = $wgTitle->getPrefixedText();
1183 if ( $wgTitle->isProtected() ) {
1184 $t = wfMsg( 'unprotectthispage' );
1185 $q = 'action=unprotect';
1187 $t = wfMsg( 'protectthispage' );
1188 $q = 'action=protect';
1190 $s = $this->makeKnownLink( $n, $t, $q );
1197 function watchThisPage() {
1198 global $wgUser, $wgOut, $wgTitle;
1200 if ( $wgOut->isArticleRelated() ) {
1201 $n = $wgTitle->getPrefixedText();
1203 if ( $wgTitle->userIsWatching() ) {
1204 $t = wfMsg( 'unwatchthispage' );
1205 $q = 'action=unwatch';
1207 $t = wfMsg( 'watchthispage' );
1208 $q = 'action=watch';
1210 $s = $this->makeKnownLink( $n, $t, $q );
1212 $s = wfMsg( 'notanarticle' );
1217 function moveThisPage() {
1218 global $wgTitle, $wgContLang;
1220 if ( $wgTitle->userCanEdit() ) {
1221 $s = $this->makeKnownLink( $wgContLang->specialPage( 'Movepage' ),
1222 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1223 } // no message if page is protected - would be redundant
1227 function historyLink() {
1230 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1231 wfMsg( 'history' ), 'action=history' );
1235 function whatLinksHere() {
1236 global $wgTitle, $wgContLang;
1238 $s = $this->makeKnownLink( $wgContLang->specialPage( 'Whatlinkshere' ),
1239 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1243 function userContribsLink() {
1244 global $wgTitle, $wgContLang;
1246 $s = $this->makeKnownLink( $wgContLang->specialPage( 'Contributions' ),
1247 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1251 function emailUserLink() {
1252 global $wgTitle, $wgContLang;
1254 $s = $this->makeKnownLink( $wgContLang->specialPage( 'Emailuser' ),
1255 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1259 function watchPageLinksLink() {
1260 global $wgOut, $wgTitle, $wgContLang;
1262 if ( ! $wgOut->isArticleRelated() ) {
1263 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1265 $s = $this->makeKnownLink( $wgContLang->specialPage(
1266 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1267 'target=' . $wgTitle->getPrefixedURL() );
1272 function otherLanguages() {
1273 global $wgOut, $wgContLang, $wgTitle, $wgUseNewInterlanguage;
1275 $a = $wgOut->getLanguageLinks();
1276 if ( 0 == count( $a ) ) {
1277 if ( !$wgUseNewInterlanguage ) return '';
1278 $ns = $wgContLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1279 if ( $ns != 0 AND $ns != 1 ) return '' ;
1281 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1282 return $this->makeKnownLink( $wgContLang->specialPage( $pn ),
1283 wfMsg( 'intl' ) , $x );
1286 if ( !$wgUseNewInterlanguage ) {
1287 $s = wfMsg( 'otherlanguages' ) . ': ';
1289 global $wgContLanguageCode ;
1290 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1291 $x .= '&xl='.$wgContLanguageCode ;
1292 $s = $this->makeKnownLink( $wgContLang->specialPage( 'Intl' ),
1293 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1296 $s = wfMsg( 'otherlanguages' ) . ': ';
1298 if($wgContLang->isRTL()) $s .= '<span dir="LTR">';
1299 foreach( $a as $l ) {
1300 if ( ! $first ) { $s .= ' | '; }
1303 $nt = Title
::newFromText( $l );
1304 $url = $nt->getFullURL();
1305 $text = $wgContLang->getLanguageName( $nt->getInterwiki() );
1307 if ( '' == $text ) { $text = $l; }
1308 $style = $this->getExternalLinkAttributes( $l, $text );
1309 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1311 if($wgContLang->isRTL()) $s .= '</span>';
1315 function bugReportsLink() {
1316 $s = $this->makeKnownLink( wfMsgForContent( 'bugreportspage' ),
1317 wfMsg( 'bugreports' ) );
1321 function dateLink() {
1322 global $wgLinkCache;
1323 $t1 = Title
::newFromText( gmdate( 'F j' ) );
1324 $t2 = Title
::newFromText( gmdate( 'Y' ) );
1326 $wgLinkCache->suspend();
1327 $id = $t1->getArticleID();
1328 $wgLinkCache->resume();
1331 $s = $this->makeBrokenLink( $t1->getText() );
1333 $s = $this->makeKnownLink( $t1->getText() );
1337 $wgLinkCache->suspend();
1338 $id = $t2->getArticleID();
1339 $wgLinkCache->resume();
1342 $s .= $this->makeBrokenLink( $t2->getText() );
1344 $s .= $this->makeKnownLink( $t2->getText() );
1349 function talkLink() {
1350 global $wgContLang, $wgTitle, $wgLinkCache;
1352 $tns = $wgTitle->getNamespace();
1353 if ( -1 == $tns ) { return ''; }
1355 $pn = $wgTitle->getText();
1356 $tp = wfMsg( 'talkpage' );
1357 if ( Namespace::isTalk( $tns ) ) {
1358 $lns = Namespace::getSubject( $tns );
1361 $text = wfMsg('articlepage');
1364 $text = wfMsg('userpage');
1367 $text = wfMsg('wikipediapage');
1370 $text = wfMsg('imagepage');
1373 $text= wfMsg('articlepage');
1377 $lns = Namespace::getTalk( $tns );
1380 $n = $wgContLang->getNsText( $lns );
1381 if ( '' == $n ) { $link = $pn; }
1382 else { $link = $n.':'.$pn; }
1384 $wgLinkCache->suspend();
1385 $s = $this->makeLink( $link, $text );
1386 $wgLinkCache->resume();
1391 function commentLink() {
1392 global $wgContLang, $wgTitle, $wgLinkCache;
1394 $tns = $wgTitle->getNamespace();
1395 if ( -1 == $tns ) { return ''; }
1397 $lns = ( Namespace::isTalk( $tns ) ) ?
$tns : Namespace::getTalk( $tns );
1399 # assert Namespace::isTalk( $lns )
1401 $n = $wgContLang->getNsText( $lns );
1402 $pn = $wgTitle->getText();
1406 $wgLinkCache->suspend();
1407 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit§ion=new');
1408 $wgLinkCache->resume();
1414 * After all the page content is transformed into HTML, it makes
1415 * a final pass through here for things like table backgrounds.
1416 * @todo probably deprecated [AV]
1418 function transformContent( $text ) {
1423 * Note: This function MUST call getArticleID() on the link,
1424 * otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1426 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1427 wfProfileIn( 'Skin::makeLink' );
1428 $nt = Title
::newFromText( $title );
1430 $result = $this->makeLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1432 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1433 $result = $text == "" ?
$title : $text;
1436 wfProfileOut( 'Skin::makeLink' );
1440 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1441 $nt = Title
::newFromText( $title );
1443 return $this->makeKnownLinkObj( Title
::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1445 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1446 return $text == '' ?
$title : $text;
1450 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1451 $nt = Title
::newFromText( $title );
1453 return $this->makeBrokenLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1455 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1456 return $text == '' ?
$title : $text;
1460 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1461 $nt = Title
::newFromText( $title );
1463 return $this->makeStubLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1465 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1466 return $text == '' ?
$title : $text;
1471 * Pass a title object, not a title string
1473 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' ) {
1474 global $wgOut, $wgUser, $wgLinkHolders;
1475 $fname = 'Skin::makeLinkObj';
1478 if ( ! isset($nt) ) {
1479 # wfDebugDieBacktrace();
1480 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1483 if ( $nt->isExternal() ) {
1484 $u = $nt->getFullURL();
1485 $link = $nt->getPrefixedURL();
1486 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1487 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1490 if ( '' != $trail ) {
1491 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1496 # Assume $this->postParseLinkColour(). This prevents
1497 # interwiki links from being parsed as external links.
1498 global $wgInterwikiLinkHolders;
1499 $t = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>";
1500 $nr = array_push($wgInterwikiLinkHolders, $t);
1501 $retVal = '<!--IWLINK '. ($nr-1) ."-->{$trail}";
1502 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1503 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1504 } elseif ( ( -1 == $nt->getNamespace() ) ||
1505 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1506 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1508 if ( $this->postParseLinkColour() ) {
1510 if ( '' != $trail ) {
1511 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1517 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1518 $nr = array_push( $wgLinkHolders['namespaces'], $nt->getNamespace() );
1519 $wgLinkHolders['dbkeys'][] = $nt->getDBkey();
1520 $wgLinkHolders['queries'][] = $query;
1521 $wgLinkHolders['texts'][] = $prefix.$text.$inside;
1522 $wgLinkHolders['titles'][] = $nt;
1524 $retVal = '<!--LINK '. ($nr-1) ."-->{$trail}";
1526 # Work out link colour immediately
1527 $aid = $nt->getArticleID() ;
1529 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1531 $threshold = $wgUser->getOption('stubthreshold') ;
1532 if ( $threshold > 0 ) {
1533 $dbr =& wfGetDB( DB_SLAVE
);
1534 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1535 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1536 if ( $s !== false ) {
1538 if ( $s->cur_is_redirect
OR $s->cur_namespace
!= 0 ) {
1539 $size = $threshold*2 ; # Really big
1541 $dbr->freeResult( $res );
1543 $size = $threshold*2 ; # Really big
1548 if ( $size < $threshold ) {
1549 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1551 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1560 * Pass a title object, not a title string
1562 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '' ) {
1563 global $wgOut, $wgTitle, $wgInputEncoding;
1565 $fname = 'Skin::makeKnownLinkObj';
1566 wfProfileIn( $fname );
1568 if ( !is_object( $nt ) ) {
1571 $link = $nt->getPrefixedURL();
1572 # if ( '' != $section && substr($section,0,1) != "#" ) {
1575 if ( '' == $link ) {
1577 if ( '' == $text ) {
1578 $text = htmlspecialchars( $nt->getFragment() );
1581 $u = $nt->escapeLocalURL( $query );
1583 if ( '' != $nt->getFragment() ) {
1584 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1585 $replacearray = array(
1589 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1591 if ( '' == $text ) {
1592 $text = htmlspecialchars( $nt->getPrefixedText() );
1594 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1597 if ( '' != $trail ) {
1598 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1603 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1604 wfProfileOut( $fname );
1609 * Pass a title object, not a title string
1611 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1612 global $wgOut, $wgUser;
1615 if ( ! isset($nt) ) {
1616 # wfDebugDieBacktrace();
1617 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1620 $fname = 'Skin::makeBrokenLinkObj';
1621 wfProfileIn( $fname );
1623 if ( '' == $query ) {
1626 $q = 'action=edit&'.$query;
1628 $u = $nt->escapeLocalURL( $q );
1630 if ( '' == $text ) {
1631 $text = htmlspecialchars( $nt->getPrefixedText() );
1633 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1636 if ( '' != $trail ) {
1637 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1642 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1643 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1645 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1648 wfProfileOut( $fname );
1653 * Pass a title object, not a title string
1655 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1656 global $wgOut, $wgUser;
1658 $link = $nt->getPrefixedURL();
1660 $u = $nt->escapeLocalURL( $query );
1662 if ( '' == $text ) {
1663 $text = htmlspecialchars( $nt->getPrefixedText() );
1665 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1668 if ( '' != $trail ) {
1669 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1674 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1675 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1677 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1682 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1683 $u = $nt->escapeLocalURL( $query );
1684 if ( '' == $text ) {
1685 $text = htmlspecialchars( $nt->getPrefixedText() );
1688 if ( '' != $trail ) {
1689 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1694 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1697 /* these are used extensively in SkinPHPTal, but also some other places */
1698 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1699 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1700 $this->checkTitle($title, $name);
1701 return $title->getLocalURL( $urlaction );
1703 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1704 $title = Title
::newFromText( $name );
1705 $title = $title->getTalkPage();
1706 $this->checkTitle($title, $name);
1707 return $title->getLocalURL( $urlaction );
1709 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1710 $title = Title
::newFromText( $name );
1711 $title= $title->getSubjectPage();
1712 $this->checkTitle($title, $name);
1713 return $title->getLocalURL( $urlaction );
1715 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1716 $title = Title
::newFromText( wfMsgForContent($name) );
1717 $this->checkTitle($title, $name);
1718 return $title->getLocalURL( $urlaction );
1720 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1721 $title = Title
::newFromText( $name );
1722 $this->checkTitle($title, $name);
1723 return $title->getLocalURL( $urlaction );
1726 # If url string starts with http, consider as external URL, else
1728 /*static*/ function makeInternalOrExternalUrl( $name ) {
1729 if ( strncmp( $name, 'http', 4 ) == 0 ) {
1732 return $this->makeUrl( $name );
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( wfMsgForContent($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 $wgContLang, $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 = $wgContLang->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, $wgContLang;
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 = $wgContLang->isRTL() ?
'left' : 'right';
2004 $textalign = $wgContLang->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.'/common/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 = $wgContLang->ucfirst( $name );
2055 return $this->makeKnownLink( $wgContLang->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, $wgContLang ;
2105 # Get rc_xxxx variables
2106 extract( $rcObj->mAttribs
) ;
2107 $curIdEq = 'curid='.$rc_cur_id;
2112 $r .= '<img src="'.$wgStylePath.'/common/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 .= $wgContLang->emphasize( ' ('.$rc_comment.')' );
2168 function recentChangesBlockGroup ( $block ) {
2169 global $wgStylePath, $wgContLang ;
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 = $wgContLang->isRTL() ?
'l' : 'r';
2203 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/common/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2204 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/common/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.'/common/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 .= $wgContLang->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, $wgContLang, $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 = $wgContLang->date( $rc_timestamp, true);
2326 $uidate = $wgLang->date( $rc_timestamp, true);
2328 if ( $date != $this->lastdate
) {
2329 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2330 $s .= "<h4>{$uidate}</h4>\n<ul class='special'>";
2331 $this->lastdate
= $date;
2332 $this->rclistOpen
= true;
2335 # If this edit has not yet been patrolled, make it stick out
2336 $s .= ( ! $wgUseRCPatrol ||
$rc_patrolled ) ?
'<li> ' : '<li class="not_patrolled"> ';
2338 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2340 $s .= '(' . wfMsg( 'diff' ) . ') (';
2342 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2345 # "[[x]] moved to [[y]]"
2346 $msg = ( $rc_type == RC_MOVE
) ?
'1movedto2' : '1movedto2_redir';
2347 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2348 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2349 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2351 $logtype = $matches[1];
2352 $logname = LogPage
::logName( $logtype );
2353 $s .= '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2356 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2357 $diffLink = wfMsg( 'diff' );
2359 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2360 ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2361 $rcidparam = "&rcid={$rc_id}";
2364 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2365 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2366 '', '', ' tabindex="'.$rc->counter
.'"');
2368 $s .= '('.$diffLink.') (';
2371 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2374 # M and N (minor and new)
2375 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2376 if ( $rc_type == RC_NEW
) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2379 # If it's a new article, there is no diff link, but if it hasn't been
2380 # patrolled yet, we need to give users a way to do so
2381 if ( $wgUseRCPatrol && $rc_type == RC_NEW
&& $rc_patrolled == 0 &&
2382 $wgUser->getID() != 0 && ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2383 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2385 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2388 $articleLink = '<strong>'.$articleLink.'</strong>';
2390 $s .= ' '.$articleLink;
2395 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2397 # User link (or contributions for unregistered users)
2398 if ( 0 == $rc_user ) {
2399 $userLink = $this->makeKnownLink( $wgContLang->specialPage( 'Contributions' ),
2400 $rc_user_text, 'target=' . $rc_user_text );
2402 $userLink = $this->makeLink( $wgContLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2407 $talkname=$wgContLang->getNsText(NS_TALK
); # use the shorter name
2408 global $wgDisableAnonTalk;
2409 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2412 $utns=$wgContLang->getNsText(NS_USER_TALK
);
2413 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2417 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2418 $blockLink = $this->makeKnownLink( $wgContLang->specialPage(
2419 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2423 if($userTalkLink) $userTalkLink .= ' | ';
2424 $userTalkLink .= $blockLink;
2426 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2429 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2430 $rc_comment=$this->formatComment($rc_comment,$rc->getTitle());
2431 $s .= $wgContLang->emphasize(' (' . $rc_comment . ')');
2438 function recentChangesLineNew( &$baseRC, $watched = false ) {
2439 global $wgTitle, $wgLang, $wgContLang, $wgUser, $wgRCSeconds;
2441 # Create a specialised object
2442 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2444 # Extract fields from DB into the function scope (rc_xxxx variables)
2445 extract( $rc->mAttribs
);
2446 $curIdEq = 'curid=' . $rc_cur_id;
2448 # If it's a new day, add the headline and flush the cache
2449 $date = $wgContLang->date( $rc_timestamp, true);
2450 $uidate = $wgLang->date( $rc_timestamp, true);
2452 if ( $date != $this->lastdate
) {
2453 # Process current cache
2454 $ret = $this->recentChangesBlock () ;
2455 $this->rc_cache
= array() ;
2456 $ret .= "<h4>{$uidate}</h4>\n";
2457 $this->lastdate
= $date;
2461 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2462 $msg = ( $rc_type == RC_MOVE
) ?
"1movedto2" : "1movedto2_redir";
2463 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2464 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2465 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2467 $logtype = $matches[1];
2468 $logname = LogPage
::logName( $logtype );
2469 $clink = '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2471 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2474 $time = $wgContLang->time( $rc_timestamp, true, $wgRCSeconds );
2475 $rc->watched
= $watched ;
2476 $rc->link
= $clink ;
2477 $rc->timestamp
= $time;
2479 # Make "cur" and "diff" links
2480 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2481 $curLink = wfMsg( 'cur' );
2482 $diffLink = wfMsg( 'diff' );
2484 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2485 $aprops = ' tabindex="'.$baseRC->counter
.'"';
2486 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2487 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2491 $titleObj = $rc->getTitle();
2492 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2493 $lastLink = wfMsg( 'last' );
2495 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2496 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2499 # Make user link (or user contributions for unregistered users)
2500 if ( $rc_user == 0 ) {
2501 $userLink = $this->makeKnownLink( $wgContLang->specialPage( 'Contributions' ),
2502 $rc_user_text, 'target=' . $rc_user_text );
2504 $userLink = $this->makeLink( $wgContLang->getNsText(
2505 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2508 $rc->userlink
= $userLink;
2509 $rc->lastlink
= $lastLink;
2510 $rc->curlink
= $curLink;
2511 $rc->difflink
= $diffLink;
2513 # Make user talk link
2514 $utns=$wgContLang->getNsText(NS_USER_TALK
);
2515 $talkname=$wgContLang->getNsText(NS_TALK
); # use the shorter name
2516 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2518 global $wgDisableAnonTalk;
2519 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2520 $blockLink = $this->makeKnownLink( $wgContLang->specialPage(
2521 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2522 if( $wgDisableAnonTalk )
2523 $rc->usertalklink
= ' ('.$blockLink.')';
2525 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2527 if( $wgDisableAnonTalk && ($rc_user == 0) )
2528 $rc->usertalklink
= '';
2530 $rc->usertalklink
= ' ('.$userTalkLink.')';
2533 # Put accumulated information into the cache, for later display
2534 # Page moves go on their own line
2535 $title = $rc->getTitle();
2536 $secureName = $title->getPrefixedDBkey();
2537 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2538 # Use an @ character to prevent collision with page names
2539 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2541 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2542 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2547 function endImageHistoryList() {
2553 * This function is called by all recent changes variants, by the page history,
2554 * and by the user contributions list. It is responsible for formatting edit
2555 * comments. It escapes any HTML in the comment, but adds some CSS to format
2556 * auto-generated comments (from section editing) and formats [[wikilinks]].
2558 * The &$title parameter must be a title OBJECT. It is used to generate a
2559 * direct link to the section in the autocomment.
2560 * @author Erik Moeller <moeller@scireview.de>
2562 * Note: there's not always a title to pass to this function.
2563 * Since you can't set a default parameter for a reference, I've turned it
2564 * temporarily to a value pass. Should be adjusted further. --brion
2566 function formatComment($comment, $title = NULL) {
2568 $comment = htmlspecialchars( $comment );
2570 # The pattern for autogen comments is / * foo * /, which makes for
2572 # We look for all comments, match any text before and after the comment,
2573 # add a separator where needed and format the comment itself with CSS
2574 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2582 # This is hackish but should work in most cases.
2583 $section=str_replace('[[','',$section);
2584 $section=str_replace(']]','',$section);
2585 $title->mFragment
=$section;
2586 $link=$this->makeKnownLinkObj($title,wfMsg('sectionlink'));
2590 if($pre) { $auto = $sep.' '.$auto; }
2591 if($post) { $auto .= ' '.$sep; }
2592 $auto='<span class="autocomment">'.$auto.'</span>';
2593 $comment=$pre.$auto.$post;
2596 # format regular and media links - all other wiki formatting
2598 $medians = $wgContLang->getNsText(Namespace::getMedia()).':';
2599 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2600 # Handle link renaming [[foo|text]] will show link as "text"
2601 if( "" != $match[3] ) {
2606 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2607 # Media link; trail not supported.
2608 $linkRegexp = '/\[\[(.*?)\]\]/';
2609 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2611 # Other kind of link
2612 if( preg_match( wfMsgForContent( "linktrail" ), $match[4], $submatch ) ) {
2613 $trail = $submatch[1];
2617 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2618 if ($match[1][0] == ':')
2619 $match[1] = substr($match[1], 1);
2620 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2622 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2627 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description ) {
2628 global $wgUser, $wgLang, $wgContLang, $wgTitle;
2630 $datetime = $wgLang->timeanddate( $timestamp, true );
2631 $del = wfMsg( 'deleteimg' );
2632 $delall = wfMsg( 'deleteimgcompletely' );
2633 $cur = wfMsg( 'cur' );
2636 $url = Image
::wfImageUrl( $img );
2638 if ( $wgUser->isSysop() ) {
2639 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2641 $style = $this->getInternalLinkAttributes( $link, $delall );
2643 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2648 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2649 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2650 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2651 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2652 urlencode( $img ) );
2653 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2654 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2656 # Having live active links for non-logged in users
2657 # means that bots and spiders crawling our site can
2658 # inadvertently change content. Baaaad idea.
2659 $rlink = wfMsg( 'revertimg' );
2664 $userlink = $usertext;
2666 $userlink = $this->makeLink( $wgContLang->getNsText( Namespace::getUser() ) .
2667 ':'.$usertext, $usertext );
2669 $nbytes = wfMsg( 'nbytes', $size );
2670 $style = $this->getInternalLinkAttributes( $url, $datetime );
2672 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2673 . " . . {$userlink} ({$nbytes})";
2675 if ( '' != $description && '*' != $description ) {
2676 $sk=$wgUser->getSkin();
2677 $s .= $wgContLang->emphasize(' (' . $sk->formatComment($description,$wgTitle) . ')');
2683 function tocIndent($level) {
2684 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2687 function tocUnindent($level) {
2688 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2692 * parameter level defines if we are on an indentation level
2694 function tocLine( $anchor, $tocline, $level ) {
2695 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2699 return '<div class="tocline">'.$link."</div>\n";
2704 function tocTable($toc) {
2705 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2706 # try min-width & co when somebody gets a chance
2707 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2709 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2710 '<b>'.wfMsg('toc').'</b>' .
2712 '</td></tr><tr id="tocinside"><td>'."\n".
2713 $toc."</td></tr></table>\n";
2717 * These two do not check for permissions: check $wgTitle->userCanEdit
2718 * before calling them
2720 function editSectionScriptForOther( $title, $section, $head ) {
2721 $ttl = Title
::newFromText( $title );
2722 $url = $ttl->escapeLocalURL( 'action=edit§ion='.$section );
2723 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2726 function editSectionScript( $section, $head ) {
2727 global $wgTitle, $wgRequest;
2728 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2731 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2732 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2735 function editSectionLinkForOther( $title, $section ) {
2737 global $wgUser, $wgContLang;
2739 $title = Title
::newFromText($title);
2740 $editurl = '§ion='.$section;
2741 $url = $this->makeKnownLink($title->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2743 if( $wgContLang->isRTL() ) {
2745 $nearside = 'right';
2750 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2754 function editSectionLink( $section ) {
2756 global $wgTitle, $wgUser, $wgContLang;
2758 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2759 # Section edit links would be out of sync on an old page.
2760 # But, if we're diffing to the current page, they'll be
2765 $editurl = '§ion='.$section;
2766 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2768 if( $wgContLang->isRTL() ) {
2770 $nearside = 'right';
2775 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2780 * This function is called by EditPage.php and shows a bulletin board style
2781 * toolbar for common editing functions. It can be disabled in the user
2783 * The necessary JavaScript code can be found in style/wikibits.js.
2785 function getEditToolbar() {
2786 global $wgStylePath, $wgLang, $wgMimeType;
2789 * toolarray an array of arrays which each include the filename of
2790 * the button image (without path), the opening tag, the closing tag,
2791 * and optionally a sample text that is inserted between the two when no
2792 * selection is highlighted.
2793 * The tip text is shown when the user moves the mouse over the button.
2795 * Already here are accesskeys (key), which are not used yet until someone
2796 * can figure out a way to make them work in IE. However, we should make
2797 * sure these keys are not defined on the edit page.
2800 array( 'image'=>'button_bold.png',
2802 'close' => "\'\'\'",
2803 'sample'=> wfMsg('bold_sample'),
2804 'tip' => wfMsg('bold_tip'),
2807 array( 'image'=>'button_italic.png',
2810 'sample'=> wfMsg('italic_sample'),
2811 'tip' => wfMsg('italic_tip'),
2814 array( 'image'=>'button_link.png',
2817 'sample'=> wfMsg('link_sample'),
2818 'tip' => wfMsg('link_tip'),
2821 array( 'image'=>'button_extlink.png',
2824 'sample'=> wfMsg('extlink_sample'),
2825 'tip' => wfMsg('extlink_tip'),
2828 array( 'image'=>'button_headline.png',
2830 'close' => " ==\\n",
2831 'sample'=> wfMsg('headline_sample'),
2832 'tip' => wfMsg('headline_tip'),
2835 array( 'image'=>'button_image.png',
2836 'open' => '[['.$wgLang->getNsText(NS_IMAGE
).":",
2838 'sample'=> wfMsg('image_sample'),
2839 'tip' => wfMsg('image_tip'),
2842 array( 'image' => 'button_media.png',
2843 'open' => '[['.$wgLang->getNsText(NS_MEDIA
).':',
2845 'sample'=> wfMsg('media_sample'),
2846 'tip' => wfMsg('media_tip'),
2849 array( 'image' => 'button_math.png',
2850 'open' => "\\<math\\>",
2851 'close' => "\\</math\\>",
2852 'sample'=> wfMsg('math_sample'),
2853 'tip' => wfMsg('math_tip'),
2856 array( 'image' => 'button_nowiki.png',
2857 'open' => "\\<nowiki\\>",
2858 'close' => "\\</nowiki\\>",
2859 'sample'=> wfMsg('nowiki_sample'),
2860 'tip' => wfMsg('nowiki_tip'),
2863 array( 'image' => 'button_sig.png',
2867 'tip' => wfMsg('sig_tip'),
2870 array( 'image' => 'button_hr.png',
2871 'open' => "\\n----\\n",
2874 'tip' => wfMsg('hr_tip'),
2878 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2880 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2881 foreach($toolarray as $tool) {
2883 $image=$wgStylePath.'/common/images/'.$tool['image'];
2884 $open=$tool['open'];
2885 $close=$tool['close'];
2886 $sample = addslashes( $tool['sample'] );
2888 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2889 // Older browsers show a "speedtip" type message only for ALT.
2890 // Ideally these should be different, realistically they
2891 // probably don't need to be.
2892 $tip = addslashes( $tool['tip'] );
2894 #$key = $tool["key"];
2896 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2899 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2900 $toolbar.="document.writeln(\"</div>\");\n";
2902 $toolbar.="/*]]>*/\n</script>";
2909 function suppressUrlExpansion() {