9 * This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
11 if( defined( "MEDIAWIKI" ) ) {
15 require_once( 'Feed.php' ); // should not be called if the actual page isn't feed enabled
16 require_once( 'Image.php' );
18 # These are the INTERNAL names, which get mapped directly to class names and
19 # file names in ./skins/. For display purposes, the Language class has
20 # internationalized names
23 $wgValidSkinNames = array(
24 'standard' => 'Standard',
25 'nostalgia' => 'Nostalgia',
26 'cologneblue' => 'CologneBlue'
29 #$wgValidSkinNames[] = 'PHPTal';
30 #$wgValidSkinNames['davinci'] = 'DaVinci';
31 #$wgValidSkinNames['mono'] = 'Mono';
32 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
33 $wgValidSkinNames['monobook'] = 'MonoBook';
34 $wgValidSkinNames['myskin'] = 'MySkin';
35 $wgValidSkinNames['chick'] = 'Chick';
39 # Get a list of all skins available in /skins/
40 # Build using the regular expression '^(.*).php$'
41 # Array keys are all lower case, array value keep the case used by filename
44 $skinDir = dir($IP.'/skins');
46 # while code from www.php.net
47 while (false !== ($file = $skinDir->read())) {
48 if(preg_match('/^(.*).php$/',$file, $matches)) {
50 $wgValidSkinNames[strtolower($aSkin)] = $aSkin;
56 require_once( 'RecentChange.php' );
62 class RCCacheEntry
extends RecentChange
64 var $secureName, $link;
65 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
66 var $userlink, $timestamp, $watched;
68 function newFromParent( $rc )
70 $rc2 = new RCCacheEntry
;
71 $rc2->mAttribs
= $rc->mAttribs
;
72 $rc2->mExtra
= $rc->mExtra
;
79 * The main skin class that provide methods and properties for all other skins
80 * including PHPTal skins.
81 * This base class is also the "Standard" skin.
88 var $lastdate, $lastline;
89 var $linktrail ; # linktrail regexp
90 var $rc_cache ; # Cache for Enhanced Recent Changes
91 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
93 var $postParseLinkColour = true;
97 global $wgUseOldExistenceCheck;
98 $postParseLinkColour = !$wgUseOldExistenceCheck;
99 $this->linktrail
= wfMsg('linktrail');
102 function getSkinNames() {
103 global $wgValidSkinNames;
104 return $wgValidSkinNames;
107 function getStylesheet() {
108 return 'common/wikistandard.css';
111 function getSkinName() {
116 * Get/set accessor for delayed link colouring
118 function postParseLinkColour( $setting = NULL ) {
119 return wfSetVar( $this->postParseLinkColour
, $setting );
122 function qbSetting() {
123 global $wgOut, $wgUser;
125 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
126 $q = $wgUser->getOption( 'quickbar' );
127 if ( '' == $q ) { $q = 0; }
131 function initPage( &$out ) {
132 $fname = 'Skin::initPage';
133 wfProfileIn( $fname );
135 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
137 $this->addMetadataLinks($out);
139 wfProfileOut( $fname );
142 function addMetadataLinks( &$out ) {
143 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
144 global $wgRightsPage, $wgRightsUrl;
146 if( $out->isArticleRelated() ) {
147 # note: buggy CC software only reads first "meta" link
148 if( $wgEnableCreativeCommonsRdf ) {
149 $out->addMetadataLink( array(
150 'title' => 'Creative Commons',
151 'type' => 'application/rdf+xml',
152 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
154 if( $wgEnableDublinCoreRdf ) {
155 $out->addMetadataLink( array(
156 'title' => 'Dublin Core',
157 'type' => 'application/rdf+xml',
158 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
162 if( $wgRightsPage ) {
163 $copy = Title
::newFromText( $wgRightsPage );
165 $copyright = $copy->getLocalURL();
168 if( !$copyright && $wgRightsUrl ) {
169 $copyright = $wgRightsUrl;
172 $out->addLink( array(
173 'rel' => 'copyright',
174 'href' => $copyright ) );
178 function outputPage( &$out ) {
179 global $wgDebugComments;
181 wfProfileIn( 'Skin::outputPage' );
182 $this->initPage( $out );
183 $out->out( $out->headElement() );
185 $out->out( "\n<body" );
186 $ops = $this->getBodyOptions();
187 foreach ( $ops as $name => $val ) {
188 $out->out( " $name='$val'" );
191 if ( $wgDebugComments ) {
192 $out->out( "<!-- Wiki debugging output:\n" .
193 $out->mDebugtext
. "-->\n" );
195 $out->out( $this->beforeContent() );
197 $out->out( $out->mBodytext
. "\n" );
199 $out->out( $this->afterContent() );
202 $out->out( $out->reportTime() );
204 $out->out( "\n</body></html>" );
207 function getHeadScripts() {
208 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
209 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/common/wikibits.js\"></script>\n";
210 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
211 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
212 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
213 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
218 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
219 function getUserStylesheet() {
220 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
221 $sheet = $this->getStylesheet();
222 $action = $wgRequest->getText('action');
223 $s = "@import \"$wgStylePath/$sheet\";\n";
224 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common/common_rtl.css\";\n";
225 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
226 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
227 $s .= $wgRequest->getText('wpTextbox1');
229 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
230 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
233 $s .= $this->doGetUserStyles();
238 * placeholder, returns generated js in monobook
240 function getUserJs() { return; }
243 * Return html code that include User stylesheets
245 function getUserStyles() {
246 global $wgOut, $wgStylePath, $wgLang;
247 $s = "<style type='text/css'>\n";
248 $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
249 $s .= $this->getUserStylesheet();
250 $s .= "/*]]>*/ /* */\n";
256 * Some styles that are set by user through the user settings interface.
258 function doGetUserStyles() {
259 global $wgUser, $wgLang;
261 $csspage = $wgLang->getNsText( NS_MEDIAWIKI
) . ':' . $this->getSkinName() . '.css';
262 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
264 if ( 1 == $wgUser->getOption( 'underline' ) ) {
265 # Don't override browser settings
269 $s .= "a { text-decoration: none; }\n";
271 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
272 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
274 if ( 1 == $wgUser->getOption( 'justify' ) ) {
275 $s .= "#article { text-align: justify; }\n";
280 function getBodyOptions() {
281 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
283 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
285 if ( 0 != $wgTitle->getNamespace() ) {
286 $a = array( 'bgcolor' => '#ffffec' );
288 else $a = array( 'bgcolor' => '#FFFFFF' );
289 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
290 (!$wgTitle->isProtected() ||
$wgUser->isSysop()) ) {
291 $t = wfMsg( 'editthispage' );
293 if ( !empty($redirect) ) {
294 $red = "&redirect={$redirect}";
296 if ( !empty($oldid) && ! isset( $diff ) ) {
297 $oid = "&oldid={$oldid}";
299 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
300 $s = 'document.location = "' .$s .'";';
301 $a +
= array ('ondblclick' => $s);
304 $a['onload'] = $wgOut->getOnloadHandler();
308 function getExternalLinkAttributes( $link, $text, $class='' ) {
309 global $wgUser, $wgOut, $wgLang;
311 $link = urldecode( $link );
312 $link = $wgLang->checkTitleEncoding( $link );
313 $link = str_replace( '_', ' ', $link );
314 $link = htmlspecialchars( $link );
316 $r = ($class != '') ?
" class='$class'" : " class='external'";
318 if ( 1 == $wgUser->getOption( 'hover' ) ) {
319 $r .= " title=\"{$link}\"";
324 function getInternalLinkAttributes( $link, $text, $broken = false ) {
325 global $wgUser, $wgOut;
327 $link = urldecode( $link );
328 $link = str_replace( '_', ' ', $link );
329 $link = htmlspecialchars( $link );
331 if ( $broken == 'stub' ) {
332 $r = ' class="stub"';
333 } else if ( $broken == 'yes' ) {
339 if ( 1 == $wgUser->getOption( 'hover' ) ) {
340 $r .= " title=\"{$link}\"";
346 * @param bool $broken
348 function getInternalLinkAttributesObj( &$nt, $text, $broken = false ) {
349 global $wgUser, $wgOut;
351 if ( $broken == 'stub' ) {
352 $r = ' class="stub"';
353 } else if ( $broken == 'yes' ) {
359 if ( 1 == $wgUser->getOption( 'hover' ) ) {
360 $r .= ' title ="' . $nt->getEscapedText() . '"';
374 * This will be called immediately after the <body> tag. Split into
375 * two functions to make it easier to subclass.
377 function beforeContent() {
378 global $wgUser, $wgOut;
380 return $this->doBeforeContent();
383 function doBeforeContent() {
384 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
385 $fname = 'Skin::doBeforeContent';
386 wfProfileIn( $fname );
389 $qb = $this->qbSetting();
391 if( $langlinks = $this->otherLanguages() ) {
397 $borderhack = 'class="top"';
400 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
401 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
404 $left = ($qb == 1 ||
$qb == 3);
405 if($wgLang->isRTL()) $left = !$left;
408 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
409 $this->logoText() . '</td>';
411 $s .= $this->getQuickbarCompensator( $rows );
413 $l = $wgLang->isRTL() ?
'right' : 'left';
414 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
416 $s .= $this->topLinks() ;
417 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
419 $r = $wgLang->isRTL() ?
"left" : "right";
420 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
421 $s .= $this->nameAndLogin();
422 $s .= "\n<br />" . $this->searchForm() . "</td>";
425 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
428 if ( $shove && !$left ) { # Right
429 $s .= $this->getQuickbarCompensator( $rows );
431 $s .= "</tr>\n</table>\n</div>\n";
432 $s .= "\n<div id='article'>\n";
434 if( $wgSiteNotice ) {
435 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
437 $s .= $this->pageTitle();
438 $s .= $this->pageSubtitle() ;
439 $s .= $this->getCategories();
440 wfProfileOut( $fname );
444 function getCategoryLinks () {
445 global $wgOut, $wgTitle, $wgUser, $wgParser;
446 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
448 if( !$wgUseCategoryMagic ) return '' ;
449 if( count( $wgOut->mCategoryLinks
) == 0 ) return '';
451 # Taken out so that they will be displayed in previews -- TS
452 #if( !$wgOut->isArticle() ) return '';
454 $t = implode ( ' | ' , $wgOut->mCategoryLinks
) ;
455 $s = $this->makeKnownLink( 'Special:Categories',
456 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
459 # optional 'dmoz-like' category browser. Will be shown under the list
460 # of categories an article belong to
461 if($wgUseCategoryBrowser) {
464 # get a big array of the parents tree
465 $parenttree = $wgTitle->getCategorieBrowser();
467 # Render the array as a serie of links
468 function walkThrough ($tree) {
470 $sk = $wgUser->getSkin();
472 foreach($tree as $element => $parent) {
474 # element start a new list
477 # grab the others elements
478 $return .= walkThrough($parent);
480 # add our current element to the list
481 $eltitle = Title
::NewFromText($element);
482 # FIXME : should be makeLink() [AV]
483 $return .= $sk->makeKnownLink($element, $eltitle->getText()).' > ';
488 $s .= walkThrough($parenttree);
494 function getCategories() {
495 $catlinks=$this->getCategoryLinks();
496 if(!empty($catlinks)) {
497 return "<p class='catlinks'>{$catlinks}</p>";
501 function getQuickbarCompensator( $rows = 1 ) {
502 return "<td width='152' rowspan='{$rows}'> </td>";
505 # This gets called immediately before the </body> tag.
507 function afterContent() {
508 global $wgUser, $wgOut, $wgServer;
509 global $wgTitle, $wgLang;
511 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
512 return $printfooter . $this->doAfterContent();
515 function printSource() {
517 $url = htmlspecialchars( $wgTitle->getFullURL() );
518 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
521 function printFooter() {
522 return "<p>" . $this->printSource() .
523 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
526 function doAfterContent() {
527 global $wgUser, $wgOut, $wgLang;
528 $fname = 'Skin::doAfterContent';
529 wfProfileIn( $fname );
530 wfProfileIn( $fname.'-1' );
532 $s = "\n</div><br style=\"clear:both\" />\n";
533 $s .= "\n<div id='footer'>";
534 $s .= '<table border="0" cellspacing="0"><tr>';
536 wfProfileOut( $fname.'-1' );
537 wfProfileIn( $fname.'-2' );
539 $qb = $this->qbSetting();
541 $left = ($qb == 1 ||
$qb == 3);
542 if($wgLang->isRTL()) $left = !$left;
544 if ( $shove && $left ) { # Left
545 $s .= $this->getQuickbarCompensator();
547 wfProfileOut( $fname.'-2' );
548 wfProfileIn( $fname.'-3' );
549 $l = $wgLang->isRTL() ?
'right' : 'left';
550 $s .= "<td class='bottom' align='$l' valign='top'>";
552 $s .= $this->bottomLinks();
553 $s .= "\n<br />" . $this->mainPageLink()
554 . ' | ' . $this->aboutLink()
555 . ' | ' . $this->specialLink( 'recentchanges' )
556 . ' | ' . $this->searchForm()
557 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
560 if ( $shove && !$left ) { # Right
561 $s .= $this->getQuickbarCompensator();
563 $s .= "</tr></table>\n</div>\n</div>\n";
565 wfProfileOut( $fname.'-3' );
566 wfProfileIn( $fname.'-4' );
567 if ( 0 != $qb ) { $s .= $this->quickBar(); }
568 wfProfileOut( $fname.'-4' );
569 wfProfileOut( $fname );
573 function pageTitleLinks() {
574 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
576 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
577 $action = $wgRequest->getText( 'action' );
579 $s = $this->printableLink();
580 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
582 if ( $wgOut->isArticleRelated() ) {
583 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
584 $name = $wgTitle->getDBkey();
585 $link = htmlspecialchars( Image
::wfImageUrl( $name ) );
586 $style = $this->getInternalLinkAttributes( $link, $name );
587 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
589 # This will show the "Approve" link if $wgUseApproval=true;
590 if ( isset ( $wgUseApproval ) && $wgUseApproval )
592 $t = $wgTitle->getDBkey();
593 $name = 'Approve this article' ;
594 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
595 #htmlspecialchars( wfImageUrl( $name ) );
596 $style = $this->getExternalLinkAttributes( $link, $name );
597 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
600 if ( 'history' == $action ||
isset( $diff ) ||
isset( $oldid ) ) {
601 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
602 wfMsg( 'currentrev' ) );
605 if ( $wgUser->getNewtalk() ) {
606 # do not show "You have new messages" text when we are viewing our
609 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
610 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
611 $n =$wgUser->getName();
612 $tl = $this->makeKnownLink( $wgLang->getNsText(
613 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
614 wfMsg('newmessageslink') );
615 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
617 $wgOut->setSquidMaxage(0);
621 $undelete = $this->getUndeleteLink();
622 if( !empty( $undelete ) ) {
623 $s .= ' | '.$undelete;
628 function getUndeleteLink() {
629 global $wgUser, $wgTitle, $wgLang, $action;
630 if( $wgUser->isSysop() &&
631 (($wgTitle->getArticleId() == 0) ||
($action == "history")) &&
632 ($n = $wgTitle->isDeleted() ) ) {
633 return wfMsg( 'thisisdeleted',
634 $this->makeKnownLink(
635 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
636 wfMsg( 'restorelink', $n ) ) );
641 function printableLink() {
642 global $wgOut, $wgFeedClasses, $wgRequest;
644 $baseurl = $_SERVER['REQUEST_URI'];
645 if( strpos( '?', $baseurl ) == false ) {
650 $baseurl = htmlspecialchars( $baseurl );
651 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
653 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
654 if( $wgOut->isSyndicated() ) {
655 foreach( $wgFeedClasses as $format => $class ) {
656 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
657 $s .= " | <a href=\"$feedurl\">{$format}</a>";
663 function pageTitle() {
664 global $wgOut, $wgTitle, $wgUser;
666 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
667 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
671 function pageSubtitle() {
674 $sub = $wgOut->getSubtitle();
676 global $wgExtraSubtitle;
677 $sub = wfMsg( 'tagline' ) . $wgExtraSubtitle;
679 $subpages = $this->subPageSubtitle();
680 $sub .= !empty($subpages)?
"</p><p class='subpages'>$subpages":'';
681 $s = "<p class='subtitle'>{$sub}</p>\n";
685 function subPageSubtitle() {
686 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
688 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
689 $ptext=$wgTitle->getPrefixedText();
690 if(preg_match('/\//',$ptext)) {
691 $links = explode('/',$ptext);
694 foreach($links as $link) {
696 if ($c<count($links)) {
697 $growinglink .= $link;
698 $getlink = $this->makeLink( $growinglink, $link );
699 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
703 $subpages .= '< ';
705 $subpages .= $getlink;
714 function nameAndLogin() {
715 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
717 $li = $wgLang->specialPage( 'Userlogin' );
718 $lo = $wgLang->specialPage( 'Userlogout' );
721 if ( 0 == $wgUser->getID() ) {
722 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
725 $tl = $this->makeKnownLink( $wgLang->getNsText(
726 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
727 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
729 $s .= $n . ' ('.$tl.')';
731 $s .= wfMsg('notloggedin');
734 $rt = $wgTitle->getPrefixedURL();
735 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
737 } else { $q = "returnto={$rt}"; }
739 $s .= "\n<br />" . $this->makeKnownLink( $li,
740 wfMsg( 'login' ), $q );
742 $n = $wgUser->getName();
743 $rt = $wgTitle->getPrefixedURL();
744 $tl = $this->makeKnownLink( $wgLang->getNsText(
745 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
746 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
750 $s .= $this->makeKnownLink( $wgLang->getNsText(
751 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
752 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
753 "returnto={$rt}" ) . ' | ' .
754 $this->specialLink( 'preferences' );
756 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
762 function getSearchLink() {
763 $searchPage =& Title
::makeTitle( NS_SPECIAL
, 'Search' );
764 return $searchPage->getLocalURL();
767 function escapeSearchLink() {
768 return htmlspecialchars( $this->getSearchLink() );
771 function searchForm() {
773 $search = $wgRequest->getText( 'search' );
775 $s = '<form name="search" class="inline" method="post" action="'
776 . $this->escapeSearchLink() . "\">\n"
777 . '<input type="text" name="search" size="19" value="'
778 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
779 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" /> '
780 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
785 function topLinks() {
789 $s = $this->mainPageLink() . $sep
790 . $this->specialLink( 'recentchanges' );
792 if ( $wgOut->isArticleRelated() ) {
793 $s .= $sep . $this->editThisPage()
794 . $sep . $this->historyLink();
796 # Many people don't like this dropdown box
797 #$s .= $sep . $this->specialPagesList();
802 function bottomLinks() {
803 global $wgOut, $wgUser, $wgTitle;
807 if ( $wgOut->isArticleRelated() ) {
808 $s .= '<strong>' . $this->editThisPage() . '</strong>';
809 if ( 0 != $wgUser->getID() ) {
810 $s .= $sep . $this->watchThisPage();
812 $s .= $sep . $this->talkLink()
813 . $sep . $this->historyLink()
814 . $sep . $this->whatLinksHere()
815 . $sep . $this->watchPageLinksLink();
817 if ( $wgTitle->getNamespace() == Namespace::getUser()
818 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
821 $id=User
::idFromName($wgTitle->getText());
822 $ip=User
::isIP($wgTitle->getText());
824 if($id ||
$ip) { # both anons and non-anons have contri list
825 $s .= $sep . $this->userContribsLink();
827 if ( 0 != $wgUser->getID() ) { # show only to signed in users
828 if($id) { # can only email non-anons
829 $s .= $sep . $this->emailUserLink();
833 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
834 $s .= "\n<br />" . $this->deleteThisPage() .
835 $sep . $this->protectThisPage() .
836 $sep . $this->moveThisPage();
838 $s .= "<br />\n" . $this->otherLanguages();
843 function pageStats() {
844 global $wgOut, $wgLang, $wgArticle, $wgRequest;
845 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
847 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
848 if ( ! $wgOut->isArticle() ) { return ''; }
849 if ( isset( $oldid ) ||
isset( $diff ) ) { return ''; }
850 if ( 0 == $wgArticle->getID() ) { return ''; }
853 if ( !$wgDisableCounters ) {
854 $count = $wgLang->formatNum( $wgArticle->getCount() );
856 $s = wfMsg( 'viewcount', $count );
860 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
861 require_once("Credits.php");
862 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
864 $s .= $this->lastModified();
867 return $s . ' ' . $this->getCopyright();
870 function getCopyright() {
871 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
874 $oldid = $wgRequest->getVal( 'oldid' );
875 $diff = $wgRequest->getVal( 'diff' );
877 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
878 $msg = 'history_copyright';
884 if( $wgRightsPage ) {
885 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
886 } elseif( $wgRightsUrl ) {
887 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
892 $out .= wfMsg( $msg, $link );
896 function getCopyrightIcon() {
897 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
899 if( $wgRightsIcon ) {
900 $icon = htmlspecialchars( $wgRightsIcon );
902 $url = htmlspecialchars( $wgRightsUrl );
903 $out .= '<a href="'.$url.'">';
905 $text = htmlspecialchars( $wgRightsText );
906 $out .= "<img src=\"$icon\" alt='$text' />";
914 function getPoweredBy() {
916 $url = htmlspecialchars( "$wgStylePath/common/images/poweredby_mediawiki_88x31.png" );
917 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
921 function lastModified() {
922 global $wgLang, $wgArticle;
924 $timestamp = $wgArticle->getTimestamp();
926 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
927 $s = ' ' . wfMsg( 'lastmodified', $d );
934 function logoText( $align = '' ) {
935 if ( '' != $align ) { $a = " align='{$align}'"; }
938 $mp = wfMsg( 'mainpage' );
939 $titleObj = Title
::newFromText( $mp );
940 if ( is_object( $titleObj ) ) {
941 $url = $titleObj->escapeLocalURL();
946 $logourl = $this->getLogo();
947 $s = "<a href='{$url}'><img{$a} src='{$logourl}' alt='[{$mp}]' /></a>";
951 function quickBar() {
952 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
953 global $wgDisableUploads, $wgRemoteUploads;
955 $fname = 'Skin::quickBar';
956 wfProfileIn( $fname );
958 $action = $wgRequest->getText( 'action' );
959 $wpPreview = $wgRequest->getBool( 'wpPreview' );
960 $tns=$wgTitle->getNamespace();
962 $s = "\n<div id='quickbar'>";
963 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
966 $s .= $this->mainPageLink()
967 . $sep . $this->specialLink( 'recentchanges' )
968 . $sep . $this->specialLink( 'randompage' );
969 if ($wgUser->getID()) {
970 $s.= $sep . $this->specialLink( 'watchlist' ) ;
971 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
972 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
975 // only show watchlist link if logged in
976 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
977 $s .= "\n<br /><hr class='sep' />";
978 $articleExists = $wgTitle->getArticleId();
979 if ( $wgOut->isArticle() ||
$action =='edit' ||
$action =='history' ||
$wpPreview) {
980 if($wgOut->isArticle()) {
981 $s .= '<strong>' . $this->editThisPage() . '</strong>';
982 } else { # backlink to the article in edit or history mode
983 if($articleExists){ # no backlink if no article
986 $text = wfMsg('articlepage');
989 $text = wfMsg('viewtalkpage');
992 $text = wfMsg('userpage');
995 $text = wfMsg('viewtalkpage');
998 $text = wfMsg('wikipediapage');
1001 $text = wfMsg('viewtalkpage');
1004 $text = wfMsg('imagepage');
1007 $text = wfMsg('viewtalkpage');
1010 $text= wfMsg('articlepage');
1013 $link = $wgTitle->getText();
1014 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
1015 $link = $nstext . ':' . $link ;
1018 $s .= $this->makeLink( $link, $text );
1019 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
1020 # we just throw in a "New page" text to tell the user that he's in edit mode,
1021 # and to avoid messing with the separator that is prepended to the next item
1022 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
1028 if( $tns%2
&& $action!='edit' && !$wpPreview) {
1029 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit§ion=new');
1033 watching could cause problems in edit mode:
1034 if user edits article, then loads "watch this article" in background and then saves
1035 article with "Watch this article" checkbox disabled, the article is transparently
1036 unwatched. Therefore we do not show the "Watch this page" link in edit mode
1038 if ( 0 != $wgUser->getID() && $articleExists) {
1039 if($action!='edit' && $action != 'submit' )
1041 $s .= $sep . $this->watchThisPage();
1043 if ( $wgTitle->userCanEdit() )
1044 $s .= $sep . $this->moveThisPage();
1046 if ( $wgUser->isSysop() and $articleExists ) {
1047 $s .= $sep . $this->deleteThisPage() .
1048 $sep . $this->protectThisPage();
1050 $s .= $sep . $this->talkLink();
1051 if ($articleExists && $action !='history') {
1052 $s .= $sep . $this->historyLink();
1054 $s.=$sep . $this->whatLinksHere();
1056 if($wgOut->isArticleRelated()) {
1057 $s .= $sep . $this->watchPageLinksLink();
1060 if ( Namespace::getUser() == $wgTitle->getNamespace()
1061 ||
$wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1064 $id=User
::idFromName($wgTitle->getText());
1065 $ip=User
::isIP($wgTitle->getText());
1068 $s .= $sep . $this->userContribsLink();
1070 if ( 0 != $wgUser->getID() ) {
1071 if($id) { # can only email real users
1072 $s .= $sep . $this->emailUserLink();
1076 $s .= "\n<br /><hr class='sep' />";
1079 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads ||
$wgRemoteUploads ) ) {
1080 $s .= $this->specialLink( 'upload' ) . $sep;
1082 $s .= $this->specialLink( 'specialpages' )
1083 . $sep . $this->bugReportsLink();
1085 global $wgSiteSupportPage;
1086 if( $wgSiteSupportPage ) {
1087 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1088 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1091 $s .= "\n<br /></div>\n";
1092 wfProfileOut( $fname );
1096 function specialPagesList() {
1097 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1098 require_once('SpecialPage.php');
1100 $pages = SpecialPage
::getPages();
1102 foreach ( $pages[''] as $name => $page ) {
1103 $a[$name] = $page->getDescription();
1105 if ( $wgUser->isSysop() )
1107 foreach ( $pages['sysop'] as $name => $page ) {
1108 $a[$name] = $page->getDescription();
1111 if ( $wgUser->isDeveloper() )
1113 foreach ( $pages['developer'] as $name => $page ) {
1114 $a[$name] = $page->getDescription() ;
1117 $go = wfMsg( 'go' );
1118 $sp = wfMsg( 'specialpages' );
1119 $spp = $wgLang->specialPage( 'Specialpages' );
1121 $s = '<form id="specialpages" method="get" class="inline" ' .
1122 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1123 $s .= "<select name=\"wpDropdown\">\n";
1124 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1126 foreach ( $a as $name => $desc ) {
1127 $p = $wgLang->specialPage( $name );
1128 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1130 $s .= "</select>\n";
1131 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1136 function mainPageLink() {
1137 $mp = wfMsg( 'mainpage' );
1138 $s = $this->makeKnownLink( $mp, $mp );
1142 function copyrightLink() {
1143 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1144 wfMsg( 'copyrightpagename' ) );
1148 function aboutLink() {
1149 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1150 wfMsg( 'aboutsite' ) );
1155 function disclaimerLink() {
1156 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1157 wfMsg( 'disclaimers' ) );
1161 function editThisPage() {
1162 global $wgOut, $wgTitle, $wgRequest;
1164 $oldid = $wgRequest->getVal( 'oldid' );
1165 $diff = $wgRequest->getVal( 'diff' );
1166 $redirect = $wgRequest->getVal( 'redirect' );
1168 if ( ! $wgOut->isArticleRelated() ) {
1169 $s = wfMsg( 'protectedpage' );
1171 $n = $wgTitle->getPrefixedText();
1172 if ( $wgTitle->userCanEdit() ) {
1173 $t = wfMsg( 'editthispage' );
1175 #$t = wfMsg( "protectedpage" );
1176 $t = wfMsg( 'viewsource' );
1180 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1181 if ( $oldid && ! isset( $diff ) ) {
1182 $oid = '&oldid='.$oldid;
1184 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1189 function deleteThisPage() {
1190 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1192 $diff = $wgRequest->getVal( 'diff' );
1193 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1194 $n = $wgTitle->getPrefixedText();
1195 $t = wfMsg( 'deletethispage' );
1197 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1204 function protectThisPage() {
1205 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1207 $diff = $wgRequest->getVal( 'diff' );
1208 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1209 $n = $wgTitle->getPrefixedText();
1211 if ( $wgTitle->isProtected() ) {
1212 $t = wfMsg( 'unprotectthispage' );
1213 $q = 'action=unprotect';
1215 $t = wfMsg( 'protectthispage' );
1216 $q = 'action=protect';
1218 $s = $this->makeKnownLink( $n, $t, $q );
1225 function watchThisPage() {
1226 global $wgUser, $wgOut, $wgTitle;
1228 if ( $wgOut->isArticleRelated() ) {
1229 $n = $wgTitle->getPrefixedText();
1231 if ( $wgTitle->userIsWatching() ) {
1232 $t = wfMsg( 'unwatchthispage' );
1233 $q = 'action=unwatch';
1235 $t = wfMsg( 'watchthispage' );
1236 $q = 'action=watch';
1238 $s = $this->makeKnownLink( $n, $t, $q );
1240 $s = wfMsg( 'notanarticle' );
1245 function moveThisPage() {
1246 global $wgTitle, $wgLang;
1248 if ( $wgTitle->userCanEdit() ) {
1249 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1250 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1251 } // no message if page is protected - would be redundant
1255 function historyLink() {
1258 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1259 wfMsg( 'history' ), 'action=history' );
1263 function whatLinksHere() {
1264 global $wgTitle, $wgLang;
1266 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1267 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1271 function userContribsLink() {
1272 global $wgTitle, $wgLang;
1274 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1275 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1279 function emailUserLink() {
1280 global $wgTitle, $wgLang;
1282 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1283 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1287 function watchPageLinksLink() {
1288 global $wgOut, $wgTitle, $wgLang;
1290 if ( ! $wgOut->isArticleRelated() ) {
1291 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1293 $s = $this->makeKnownLink( $wgLang->specialPage(
1294 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1295 'target=' . $wgTitle->getPrefixedURL() );
1300 function otherLanguages() {
1301 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1303 $a = $wgOut->getLanguageLinks();
1304 if ( 0 == count( $a ) ) {
1305 if ( !$wgUseNewInterlanguage ) return '';
1306 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1307 if ( $ns != 0 AND $ns != 1 ) return '' ;
1309 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1310 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1311 wfMsg( 'intl' ) , $x );
1314 if ( !$wgUseNewInterlanguage ) {
1315 $s = wfMsg( 'otherlanguages' ) . ': ';
1317 global $wgLanguageCode ;
1318 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1319 $x .= '&xl='.$wgLanguageCode ;
1320 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1321 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1324 $s = wfMsg( 'otherlanguages' ) . ': ';
1326 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1327 foreach( $a as $l ) {
1328 if ( ! $first ) { $s .= ' | '; }
1331 $nt = Title
::newFromText( $l );
1332 $url = $nt->getFullURL();
1333 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1335 if ( '' == $text ) { $text = $l; }
1336 $style = $this->getExternalLinkAttributes( $l, $text );
1337 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1339 if($wgLang->isRTL()) $s .= '</span>';
1343 function bugReportsLink() {
1344 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1345 wfMsg( 'bugreports' ) );
1349 function dateLink() {
1350 global $wgLinkCache;
1351 $t1 = Title
::newFromText( gmdate( 'F j' ) );
1352 $t2 = Title
::newFromText( gmdate( 'Y' ) );
1354 $wgLinkCache->suspend();
1355 $id = $t1->getArticleID();
1356 $wgLinkCache->resume();
1359 $s = $this->makeBrokenLink( $t1->getText() );
1361 $s = $this->makeKnownLink( $t1->getText() );
1365 $wgLinkCache->suspend();
1366 $id = $t2->getArticleID();
1367 $wgLinkCache->resume();
1370 $s .= $this->makeBrokenLink( $t2->getText() );
1372 $s .= $this->makeKnownLink( $t2->getText() );
1377 function talkLink() {
1378 global $wgLang, $wgTitle, $wgLinkCache;
1380 $tns = $wgTitle->getNamespace();
1381 if ( -1 == $tns ) { return ''; }
1383 $pn = $wgTitle->getText();
1384 $tp = wfMsg( 'talkpage' );
1385 if ( Namespace::isTalk( $tns ) ) {
1386 $lns = Namespace::getSubject( $tns );
1389 $text = wfMsg('articlepage');
1392 $text = wfMsg('userpage');
1395 $text = wfMsg('wikipediapage');
1398 $text = wfMsg('imagepage');
1401 $text= wfMsg('articlepage');
1405 $lns = Namespace::getTalk( $tns );
1408 $n = $wgLang->getNsText( $lns );
1409 if ( '' == $n ) { $link = $pn; }
1410 else { $link = $n.':'.$pn; }
1412 $wgLinkCache->suspend();
1413 $s = $this->makeLink( $link, $text );
1414 $wgLinkCache->resume();
1419 function commentLink() {
1420 global $wgLang, $wgTitle, $wgLinkCache;
1422 $tns = $wgTitle->getNamespace();
1423 if ( -1 == $tns ) { return ''; }
1425 $lns = ( Namespace::isTalk( $tns ) ) ?
$tns : Namespace::getTalk( $tns );
1427 # assert Namespace::isTalk( $lns )
1429 $n = $wgLang->getNsText( $lns );
1430 $pn = $wgTitle->getText();
1434 $wgLinkCache->suspend();
1435 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit§ion=new');
1436 $wgLinkCache->resume();
1442 * After all the page content is transformed into HTML, it makes
1443 * a final pass through here for things like table backgrounds.
1444 * @todo probably deprecated [AV]
1446 function transformContent( $text ) {
1451 * Note: This function MUST call getArticleID() on the link,
1452 * otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1454 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1455 wfProfileIn( 'Skin::makeLink' );
1456 $nt = Title
::newFromText( $title );
1458 $result = $this->makeLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1460 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1461 $result = $text == "" ?
$title : $text;
1464 wfProfileOut( 'Skin::makeLink' );
1468 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1469 $nt = Title
::newFromText( $title );
1471 return $this->makeKnownLinkObj( Title
::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1473 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1474 return $text == '' ?
$title : $text;
1478 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1479 $nt = Title
::newFromText( $title );
1481 return $this->makeBrokenLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1483 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1484 return $text == '' ?
$title : $text;
1488 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1489 $nt = Title
::newFromText( $title );
1491 return $this->makeStubLinkObj( Title
::newFromText( $title ), $text, $query, $trail );
1493 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1494 return $text == '' ?
$title : $text;
1499 * Pass a title object, not a title string
1501 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' ) {
1502 global $wgOut, $wgUser;
1503 $fname = 'Skin::makeLinkObj';
1507 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1509 if ( $nt->isExternal() ) {
1510 $u = $nt->getFullURL();
1511 $link = $nt->getPrefixedURL();
1512 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1513 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1516 if ( '' != $trail ) {
1517 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1522 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1523 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1524 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1525 } elseif ( ( -1 == $nt->getNamespace() ) ||
1526 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1527 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1529 if ( $this->postParseLinkColour() ) {
1531 if ( '' != $trail ) {
1532 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1538 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1539 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1540 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1542 # Work out link colour immediately
1543 $aid = $nt->getArticleID() ;
1545 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1547 $threshold = $wgUser->getOption('stubthreshold') ;
1548 if ( $threshold > 0 ) {
1549 $dbr =& wfGetDB( DB_SLAVE
);
1550 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1551 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1552 if ( $s !== false ) {
1554 if ( $s->cur_is_redirect
OR $s->cur_namespace
!= 0 ) {
1555 $size = $threshold*2 ; # Really big
1557 $dbr->freeResult( $res );
1559 $size = $threshold*2 ; # Really big
1564 if ( $size < $threshold ) {
1565 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1567 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1576 * Pass a title object, not a title string
1578 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '' ) {
1579 global $wgOut, $wgTitle, $wgInputEncoding;
1581 $fname = 'Skin::makeKnownLinkObj';
1582 wfProfileIn( $fname );
1584 if ( !is_object( $nt ) ) {
1587 $link = $nt->getPrefixedURL();
1588 # if ( '' != $section && substr($section,0,1) != "#" ) {
1591 if ( '' == $link ) {
1593 if ( '' == $text ) {
1594 $text = htmlspecialchars( $nt->getFragment() );
1597 $u = $nt->escapeLocalURL( $query );
1599 if ( '' != $nt->getFragment() ) {
1600 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT
, $wgInputEncoding ) );
1601 $replacearray = array(
1605 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1607 if ( '' == $text ) {
1608 $text = htmlspecialchars( $nt->getPrefixedText() );
1610 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1613 if ( '' != $trail ) {
1614 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1619 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1620 wfProfileOut( $fname );
1625 * Pass a title object, not a title string
1627 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1628 global $wgOut, $wgUser;
1632 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1634 $fname = 'Skin::makeBrokenLinkObj';
1635 wfProfileIn( $fname );
1637 if ( '' == $query ) {
1640 $q = 'action=edit&'.$query;
1642 $u = $nt->escapeLocalURL( $q );
1644 if ( '' == $text ) {
1645 $text = htmlspecialchars( $nt->getPrefixedText() );
1647 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1650 if ( '' != $trail ) {
1651 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1656 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1657 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1659 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1662 wfProfileOut( $fname );
1667 * Pass a title object, not a title string
1669 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1670 global $wgOut, $wgUser;
1672 $link = $nt->getPrefixedURL();
1674 $u = $nt->escapeLocalURL( $query );
1676 if ( '' == $text ) {
1677 $text = htmlspecialchars( $nt->getPrefixedText() );
1679 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1682 if ( '' != $trail ) {
1683 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1688 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1689 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1691 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1696 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
1697 $u = $nt->escapeLocalURL( $query );
1698 if ( '' == $text ) {
1699 $text = htmlspecialchars( $nt->getPrefixedText() );
1702 if ( '' != $trail ) {
1703 if ( preg_match( $this->linktrail
, $trail, $m ) ) {
1708 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1711 /* these are used extensively in SkinPHPTal, but also some other places */
1712 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1713 $title = Title
::makeTitle( NS_SPECIAL
, $name );
1714 $this->checkTitle($title, $name);
1715 return $title->getLocalURL( $urlaction );
1717 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1718 $title = Title
::newFromText( $name );
1719 $title = $title->getTalkPage();
1720 $this->checkTitle($title, $name);
1721 return $title->getLocalURL( $urlaction );
1723 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1724 $title = Title
::newFromText( $name );
1725 $title= $title->getSubjectPage();
1726 $this->checkTitle($title, $name);
1727 return $title->getLocalURL( $urlaction );
1729 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1730 $title = Title
::newFromText( wfMsg($name) );
1731 $this->checkTitle($title, $name);
1732 return $title->getLocalURL( $urlaction );
1734 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1735 $title = Title
::newFromText( $name );
1736 $this->checkTitle($title, $name);
1737 return $title->getLocalURL( $urlaction );
1739 # this can be passed the NS number as defined in Language.php
1740 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1741 $title = Title
::makeTitleSafe( $namespace, $name );
1742 $this->checkTitle($title, $name);
1743 return $title->getLocalURL( $urlaction );
1746 /* these return an array with the 'href' and boolean 'exists' */
1747 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1748 $title = Title
::newFromText( $name );
1749 $this->checkTitle($title, $name);
1751 'href' => $title->getLocalURL( $urlaction ),
1752 'exists' => $title->getArticleID() != 0?
true:false
1755 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1756 $title = Title
::newFromText( $name );
1757 $title = $title->getTalkPage();
1758 $this->checkTitle($title, $name);
1760 'href' => $title->getLocalURL( $urlaction ),
1761 'exists' => $title->getArticleID() != 0?
true:false
1764 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1765 $title = Title
::newFromText( $name );
1766 $title= $title->getSubjectPage();
1767 $this->checkTitle($title, $name);
1769 'href' => $title->getLocalURL( $urlaction ),
1770 'exists' => $title->getArticleID() != 0?
true:false
1773 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1774 $title = Title
::newFromText( wfMsg($name) );
1775 $this->checkTitle($title, $name);
1777 'href' => $title->getLocalURL( $urlaction ),
1778 'exists' => $title->getArticleID() != 0?
true:false
1782 # make sure we have some title to operate on
1783 /*static*/ function checkTitle ( &$title, &$name ) {
1784 if(!is_object($title)) {
1785 $title = Title
::newFromText( $name );
1786 if(!is_object($title)) {
1787 $title = Title
::newFromText( '--error: link target missing--' );
1792 function fnamePart( $url ) {
1793 $basename = strrchr( $url, '/' );
1794 if ( false === $basename ) {
1797 $basename = substr( $basename, 1 );
1799 return htmlspecialchars( $basename );
1802 function makeImage( $url, $alt = '' ) {
1806 $alt = $this->fnamePart( $url );
1808 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1812 function makeImageLink( $name, $url, $alt = '' ) {
1813 $nt = Title
::makeTitleSafe( NS_IMAGE
, $name );
1814 return $this->makeImageLinkObj( $nt, $alt );
1817 function makeImageLinkObj( $nt, $alt = '' ) {
1818 global $wgLang, $wgUseImageResize;
1819 $img = Image
::newFromTitle( $nt );
1820 $url = $img->getURL();
1823 $prefix = $postfix = '';
1825 if ( $wgUseImageResize ) {
1826 # Check if the alt text is of the form "options|alt text"
1828 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1829 # * left no resizing, just left align. label is used for alt= only
1830 # * right same, but right aligned
1831 # * none same, but not aligned
1832 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1833 # * center center the image
1834 # * framed Keep original image size, no magnify-button.
1836 $part = explode( '|', $alt);
1838 $mwThumb =& MagicWord
::get( MAG_IMG_THUMBNAIL
);
1839 $mwLeft =& MagicWord
::get( MAG_IMG_LEFT
);
1840 $mwRight =& MagicWord
::get( MAG_IMG_RIGHT
);
1841 $mwNone =& MagicWord
::get( MAG_IMG_NONE
);
1842 $mwWidth =& MagicWord
::get( MAG_IMG_WIDTH
);
1843 $mwCenter =& MagicWord
::get( MAG_IMG_CENTER
);
1844 $mwFramed =& MagicWord
::get( MAG_IMG_FRAMED
);
1845 $alt = $part[count($part)-1];
1847 $height = $framed = $thumb = false;
1848 $manual_thumb = "" ;
1850 foreach( $part as $key => $val ) {
1851 $val_parts = explode ( "=" , $val , 2 ) ;
1852 $left_part = array_shift ( $val_parts ) ;
1853 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1855 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1856 # use manually specified thumbnail
1858 $manual_thumb = array_shift ( $val_parts ) ;
1859 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1860 # remember to set an alignment, don't render immediately
1862 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1863 # remember to set an alignment, don't render immediately
1865 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1866 # remember to set an alignment, don't render immediately
1868 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1869 # remember to set an alignment, don't render immediately
1871 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1872 # $match is the image width in pixels
1873 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1874 $width = intval( $m[1] );
1875 $height = intval( $m[2] );
1877 $width = intval($match);
1879 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1883 if ( 'center' == $align )
1885 $prefix = '<span style="text-align: center">';
1886 $postfix = '</span>';
1890 if ( $thumb ||
$framed ) {
1892 # Create a thumbnail. Alignment depends on language
1893 # writing direction, # right aligned for left-to-right-
1894 # languages ("Western languages"), left-aligned
1895 # for right-to-left-languages ("Semitic languages")
1897 # If thumbnail width has not been provided, it is set
1898 # here to 180 pixels
1899 if ( $align == '' ) {
1900 $align = $wgLang->isRTL() ?
'left' : 'right';
1902 if ( ! isset($width) ) {
1905 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1907 } elseif ( isset($width) ) {
1909 # Create a resized image, without the additional thumbnail
1912 if ( ( ! $height === false )
1913 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1914 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1915 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1916 $width = $img->getWidth() * $height / $img->getHeight();
1918 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1920 } # endif $wgUseImageResize
1922 if ( empty( $alt ) ) {
1923 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1925 $alt = htmlspecialchars( $alt );
1927 $u = $nt->escapeLocalURL();
1930 $s = wfMsg( 'missingimage', $img->getName() );
1931 $s .= "<br>{$alt}<br>{$url}<br>\n";
1933 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1934 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1936 if ( '' != $align ) {
1937 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1939 return str_replace("\n", ' ',$prefix.$s.$postfix);
1943 * Make HTML for a thumbnail including image, border and caption
1944 * $img is an Image object
1946 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1947 global $wgStylePath, $wgLang;
1948 # $image = Title::makeTitleSafe( NS_IMAGE, $name );
1949 $url = $img->getURL();
1951 #$label = htmlspecialchars( $label );
1952 $alt = preg_replace( '/<[^>]*>/', '', $label);
1953 $alt = htmlspecialchars( $alt );
1955 $width = $height = 0;
1956 if ( $img->exists() )
1958 $width = $img->getWidth();
1959 $height = $img->getHeight();
1961 if ( 0 == $width ||
0 == $height )
1963 $width = $height = 200;
1965 if ( $boxwidth == 0 )
1971 // Use image dimensions, don't scale
1973 $oboxwidth = $boxwidth +
2;
1974 $boxheight = $height;
1977 $h = intval( $height/($width/$boxwidth) );
1978 $oboxwidth = $boxwidth +
2;
1979 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1981 $boxwidth *= $boxheight/$h;
1985 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1988 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1990 $manual_title = Title
::makeTitleSafe( NS_IMAGE
, $manual_thumb ); #new Title ( $manual_thumb ) ;
1991 $manual_img = Image
::newFromTitle( $manual_title );
1992 $thumbUrl = $manual_img->getURL();
1993 if ( $manual_img->exists() )
1995 $width = $manual_img->getWidth();
1996 $height = $manual_img->getHeight();
1997 $boxwidth = $width ;
1998 $boxheight = $height ;
1999 $oboxwidth = $boxwidth +
2 ;
2003 $u = $img->getEscapeLocalURL();
2005 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
2006 $magnifyalign = $wgLang->isRTL() ?
'left' : 'right';
2007 $textalign = $wgLang->isRTL() ?
' style="text-align:right"' : '';
2009 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
2010 if ( $thumbUrl == '' ) {
2011 $s .= wfMsg( 'missingimage', $img->getName() );
2014 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
2015 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
2016 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
2020 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
2021 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
2022 '<img src="'.$wgStylePath.'/common/images/magnify-clip.png" ' .
2023 'width="15" height="11" alt="'.$more.'" /></a></div>';
2026 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
2027 return str_replace("\n", ' ', $s);
2030 function makeMediaLink( $name, $url, $alt = '' ) {
2031 $nt = Title
::makeTitleSafe( Namespace::getMedia(), $name );
2032 return $this->makeMediaLinkObj( $nt, $alt );
2035 function makeMediaLinkObj( $nt, $alt = '' ) {
2036 if ( ! isset( $nt ) )
2038 ### HOTFIX. Instead of breaking, return empty string.
2041 $name = $nt->getDBKey();
2042 $url = Image
::wfImageUrl( $name );
2043 if ( empty( $alt ) ) {
2044 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2047 $u = htmlspecialchars( $url );
2048 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2053 function specialLink( $name, $key = '' ) {
2056 if ( '' == $key ) { $key = strtolower( $name ); }
2057 $pn = $wgLang->ucfirst( $name );
2058 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2062 function makeExternalLink( $url, $text, $escape = true ) {
2063 $style = $this->getExternalLinkAttributes( $url, $text );
2064 $url = htmlspecialchars( $url );
2066 $text = htmlspecialchars( $text );
2068 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2071 # Called by history lists and recent changes
2074 # Returns text for the start of the tabular part of RC
2075 function beginRecentChangesList() {
2076 $this->rc_cache
= array() ;
2077 $this->rcMoveIndex
= 0;
2078 $this->rcCacheIndex
= 0 ;
2079 $this->lastdate
= '';
2080 $this->rclistOpen
= false;
2084 function beginImageHistoryList() {
2085 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2086 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2091 * Returns text for the end of RC
2092 * If enhanced RC is in use, returns pretty much all the text
2094 function endRecentChangesList() {
2095 $s = $this->recentChangesBlock() ;
2096 if( $this->rclistOpen
) {
2103 * Enhanced RC ungrouped line
2105 function recentChangesBlockLine ( $rcObj ) {
2106 global $wgStylePath, $wgLang ;
2108 # Get rc_xxxx variables
2109 extract( $rcObj->mAttribs
) ;
2110 $curIdEq = 'curid='.$rc_cur_id;
2115 $r .= '<img src="'.$wgStylePath.'/common/images/Arr_.png" width="12" height="12" border="0" />' ;
2118 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2119 $r .= ' ';
2121 # M & N (minor & new)
2122 $M = wfMsg( 'minoreditletter' );
2123 $N = wfMsg( 'newpageletter' );
2125 if ( $rc_type == RC_NEW
) {
2138 $r .= ' '.$rcObj->timestamp
.' ' ;
2142 $link = $rcObj->link
;
2143 if ( $rcObj->watched
) $link = '<strong>'.$link.'</strong>' ;
2148 $r .= $rcObj->difflink
;
2152 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2155 $r .= ') . . '.$rcObj->userlink
;
2156 $r .= $rcObj->usertalklink
;
2159 if ( $rc_comment != '' && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2160 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2161 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2171 function recentChangesBlockGroup ( $block ) {
2172 global $wgStylePath, $wgLang ;
2175 $M = wfMsg( 'minoreditletter' );
2176 $N = wfMsg( 'newpageletter' );
2178 # Collate list of users
2180 $userlinks = array () ;
2181 foreach ( $block AS $rcObj ) {
2182 $oldid = $rcObj->mAttribs
['rc_last_oldid'];
2183 if ( $rcObj->mAttribs
['rc_new'] ) $isnew = true ;
2184 $u = $rcObj->userlink
;
2185 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2189 # Sort the list and convert to text
2190 krsort ( $userlinks ) ;
2191 asort ( $userlinks ) ;
2193 foreach ( $userlinks as $userlink => $count) {
2195 if ( $count > 1 ) $text .= " ({$count}×)" ;
2196 array_push ( $users , $text ) ;
2198 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2201 $rci = 'RCI'.$this->rcCacheIndex
;
2202 $rcl = 'RCL'.$this->rcCacheIndex
;
2203 $rcm = 'RCM'.$this->rcCacheIndex
;
2204 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2205 $arrowdir = $wgLang->isRTL() ?
'l' : 'r';
2206 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/common/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2207 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/common/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2213 if ( $isnew ) $r .= $N ;
2214 else $r .= ' ' ;
2215 $r .= ' ' ; # Minor
2218 $r .= ' '.$block[0]->timestamp
.' ' ;
2222 $link = $block[0]->link
;
2223 if ( $block[0]->watched
) $link = '<strong>'.$link.'</strong>' ;
2226 $curIdEq = 'curid=' . $block[0]->mAttribs
['rc_cur_id'];
2227 if ( $block[0]->mAttribs
['rc_type'] != RC_LOG
) {
2229 $r .= ' ('.count($block).' ' ;
2230 if ( $isnew ) $r .= wfMsg('changes');
2231 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2232 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2236 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2244 $r .= '<div id="'.$rci.'" style="display:none">' ;
2245 foreach ( $block AS $rcObj ) {
2246 # Get rc_xxxx variables
2247 extract( $rcObj->mAttribs
);
2249 $r .= '<img src="'.$wgStylePath.'/common/images/Arr_.png" width="12" height="12" />';
2250 $r .= '<tt> ' ;
2251 if ( $rc_new ) $r .= $N ;
2252 else $r .= ' ' ;
2253 if ( $rc_minor ) $r .= $M ;
2254 else $r .= ' ' ;
2258 if ( $rc_last_oldid != 0 ) {
2259 $o = 'oldid='.$rc_last_oldid ;
2261 if ( $rc_type == RC_LOG
) {
2262 $link = $rcObj->timestamp
;
2264 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp
, "{$curIdEq}&$o" ) ;
2266 $link = '<tt>'.$link.'</tt>' ;
2270 $r .= $rcObj->curlink
;
2272 $r .= $rcObj->lastlink
;
2273 $r .= ') . . '.$rcObj->userlink
;
2274 $r .= $rcObj->usertalklink
;
2275 if ( $rc_comment != '' ) {
2276 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2277 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2283 $this->rcCacheIndex++
;
2288 * If enhanced RC is in use, this function takes the previously cached
2289 * RC lines, arranges them, and outputs the HTML
2291 function recentChangesBlock () {
2292 global $wgStylePath ;
2293 if ( count ( $this->rc_cache
) == 0 ) return '' ;
2295 foreach ( $this->rc_cache
AS $secureName => $block ) {
2296 if ( count ( $block ) < 2 ) {
2297 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2299 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2303 return '<div>'.$blockOut.'</div>' ;
2307 * Called in a loop over all displayed RC entries
2308 * Either returns the line, or caches it for later use
2310 function recentChangesLine( &$rc, $watched = false ) {
2312 $usenew = $wgUser->getOption( 'usenewrc' );
2314 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2316 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2320 function recentChangesLineOld( &$rc, $watched = false ) {
2321 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2323 # Extract DB fields into local scope
2324 extract( $rc->mAttribs
);
2325 $curIdEq = 'curid=' . $rc_cur_id;
2327 # Make date header if necessary
2328 $date = $wgLang->date( $rc_timestamp, true);
2330 if ( $date != $this->lastdate
) {
2331 if ( '' != $this->lastdate
) { $s .= "</ul>\n"; }
2332 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2333 $this->lastdate
= $date;
2334 $this->rclistOpen
= true;
2337 # If this edit has not yet been patrolled, make it stick out
2338 $s .= ( ! $wgUseRCPatrol ||
$rc_patrolled ) ?
'<li> ' : '<li class="not_patrolled"> ';
2340 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2342 $s .= '(' . wfMsg( 'diff' ) . ') (';
2344 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2347 # "[[x]] moved to [[y]]"
2348 $msg = ( $rc_type == RC_MOVE
) ?
'1movedto2' : '1movedto2_redir';
2349 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2350 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2351 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2353 $logtype = $matches[1];
2354 $logname = LogPage
::logName( $logtype );
2355 $s .= '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2358 if ( $rc_type == RC_NEW ||
$rc_type == RC_LOG
) {
2359 $diffLink = wfMsg( 'diff' );
2361 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2362 ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2363 $rcidparam = "&rcid={$rc_id}";
2366 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2367 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2368 '', '', ' tabindex="'.$rc->counter
.'"');
2370 $s .= '('.$diffLink.') (';
2373 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2376 # M and N (minor and new)
2377 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2378 if ( $rc_type == RC_NEW
) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2381 # If it's a new article, there is no diff link, but if it hasn't been
2382 # patrolled yet, we need to give users a way to do so
2383 if ( $wgUseRCPatrol && $rc_type == RC_NEW
&& $rc_patrolled == 0 &&
2384 $wgUser->getID() != 0 && ( $wgUser->isSysop() ||
!$wgOnlySysopsCanPatrol ) )
2385 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2387 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2390 $articleLink = '<strong>'.$articleLink.'</strong>';
2392 $s .= ' '.$articleLink;
2397 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2399 # User link (or contributions for unregistered users)
2400 if ( 0 == $rc_user ) {
2401 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2402 $rc_user_text, 'target=' . $rc_user_text );
2404 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER
) . ':'.$rc_user_text, $rc_user_text );
2409 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2410 global $wgDisableAnonTalk;
2411 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2414 $utns=$wgLang->getNsText(NS_USER_TALK
);
2415 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2419 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2420 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2421 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2425 if($userTalkLink) $userTalkLink .= ' | ';
2426 $userTalkLink .= $blockLink;
2428 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2431 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE
&& $rc_type != RC_MOVE_OVER_REDIRECT
) {
2432 $rc_comment=$this->formatComment($rc_comment,$rc->getTitle());
2433 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2440 function recentChangesLineNew( &$baseRC, $watched = false ) {
2441 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2443 # Create a specialised object
2444 $rc = RCCacheEntry
::newFromParent( $baseRC ) ;
2446 # Extract fields from DB into the function scope (rc_xxxx variables)
2447 extract( $rc->mAttribs
);
2448 $curIdEq = 'curid=' . $rc_cur_id;
2450 # If it's a new day, add the headline and flush the cache
2451 $date = $wgLang->date( $rc_timestamp, true);
2453 if ( $date != $this->lastdate
) {
2454 # Process current cache
2455 $ret = $this->recentChangesBlock () ;
2456 $this->rc_cache
= array() ;
2457 $ret .= "<h4>{$date}</h4>\n";
2458 $this->lastdate
= $date;
2462 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2463 $msg = ( $rc_type == RC_MOVE
) ?
"1movedto2" : "1movedto2_redir";
2464 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2465 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2466 } elseif( $rc_namespace == NS_SPECIAL
&& preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2468 $logtype = $matches[1];
2469 $logname = LogPage
::logName( $logtype );
2470 $clink = '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2472 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2475 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2476 $rc->watched
= $watched ;
2477 $rc->link
= $clink ;
2478 $rc->timestamp
= $time;
2480 # Make "cur" and "diff" links
2481 if ( ( $rc_type == RC_NEW
&& $rc_this_oldid == 0 ) ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2482 $curLink = wfMsg( 'cur' );
2483 $diffLink = wfMsg( 'diff' );
2485 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2486 $aprops = ' tabindex="'.$baseRC->counter
.'"';
2487 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2488 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2492 $titleObj = $rc->getTitle();
2493 if ( $rc_last_oldid == 0 ||
$rc_type == RC_LOG ||
$rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2494 $lastLink = wfMsg( 'last' );
2496 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2497 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2500 # Make user link (or user contributions for unregistered users)
2501 if ( $rc_user == 0 ) {
2502 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2503 $rc_user_text, 'target=' . $rc_user_text );
2505 $userLink = $this->makeLink( $wgLang->getNsText(
2506 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2509 $rc->userlink
= $userLink;
2510 $rc->lastlink
= $lastLink;
2511 $rc->curlink
= $curLink;
2512 $rc->difflink
= $diffLink;
2514 # Make user talk link
2515 $utns=$wgLang->getNsText(NS_USER_TALK
);
2516 $talkname=$wgLang->getNsText(NS_TALK
); # use the shorter name
2517 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2519 global $wgDisableAnonTalk;
2520 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2521 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2522 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2523 if( $wgDisableAnonTalk )
2524 $rc->usertalklink
= ' ('.$blockLink.')';
2526 $rc->usertalklink
= ' ('.$userTalkLink.' | '.$blockLink.')';
2528 if( $wgDisableAnonTalk && ($rc_user == 0) )
2529 $rc->usertalklink
= '';
2531 $rc->usertalklink
= ' ('.$userTalkLink.')';
2534 # Put accumulated information into the cache, for later display
2535 # Page moves go on their own line
2536 $title = $rc->getTitle();
2537 $secureName = $title->getPrefixedDBkey();
2538 if ( $rc_type == RC_MOVE ||
$rc_type == RC_MOVE_OVER_REDIRECT
) {
2539 # Use an @ character to prevent collision with page names
2540 $this->rc_cache
['@@' . ($this->rcMoveIndex++
)] = array($rc);
2542 if ( !isset ( $this->rc_cache
[$secureName] ) ) $this->rc_cache
[$secureName] = array() ;
2543 array_push ( $this->rc_cache
[$secureName] , $rc ) ;
2548 function endImageHistoryList() {
2554 * This function is called by all recent changes variants, by the page history,
2555 * and by the user contributions list. It is responsible for formatting edit
2556 * comments. It escapes any HTML in the comment, but adds some CSS to format
2557 * auto-generated comments (from section editing) and formats [[wikilinks]].
2559 * The &$title parameter must be a title OBJECT. It is used to generate a
2560 * direct link to the section in the autocomment.
2561 * @author Erik Moeller <moeller@scireview.de>
2563 * Note: there's not always a title to pass to this function.
2564 * Since you can't set a default parameter for a reference, I've turned it
2565 * temporarily to a value pass. Should be adjusted further. --brion
2567 function formatComment($comment, $title = NULL) {
2569 $comment = htmlspecialchars( $comment );
2571 # The pattern for autogen comments is / * foo * /, which makes for
2573 # We look for all comments, match any text before and after the comment,
2574 # add a separator where needed and format the comment itself with CSS
2575 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2583 # This is hackish but should work in most cases.
2584 $section=str_replace('[[','',$section);
2585 $section=str_replace(']]','',$section);
2586 $title->mFragment
=$section;
2587 $link=$this->makeKnownLinkObj($title,wfMsg('sectionlink'));
2591 if($pre) { $auto = $sep.' '.$auto; }
2592 if($post) { $auto .= ' '.$sep; }
2593 $auto='<span class="autocomment">'.$auto.'</span>';
2594 $comment=$pre.$auto.$post;
2597 # format regular and media links - all other wiki formatting
2599 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2600 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2601 # Handle link renaming [[foo|text]] will show link as "text"
2602 if( "" != $match[3] ) {
2607 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2608 # Media link; trail not supported.
2609 $linkRegexp = '/\[\[(.*?)\]\]/';
2610 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2612 # Other kind of link
2613 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2614 $trail = $submatch[1];
2618 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2619 if ($match[1][0] == ':')
2620 $match[1] = substr($match[1], 1);
2621 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2623 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2628 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description ) {
2629 global $wgUser, $wgLang, $wgTitle;
2631 $datetime = $wgLang->timeanddate( $timestamp, true );
2632 $del = wfMsg( 'deleteimg' );
2633 $delall = wfMsg( 'deleteimgcompletely' );
2634 $cur = wfMsg( 'cur' );
2637 $url = Image
::wfImageUrl( $img );
2639 if ( $wgUser->isSysop() ) {
2640 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2642 $style = $this->getInternalLinkAttributes( $link, $delall );
2644 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2649 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2650 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2651 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2652 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2653 urlencode( $img ) );
2654 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2655 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2657 # Having live active links for non-logged in users
2658 # means that bots and spiders crawling our site can
2659 # inadvertently change content. Baaaad idea.
2660 $rlink = wfMsg( 'revertimg' );
2665 $userlink = $usertext;
2667 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2668 ':'.$usertext, $usertext );
2670 $nbytes = wfMsg( 'nbytes', $size );
2671 $style = $this->getInternalLinkAttributes( $url, $datetime );
2673 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2674 . " . . {$userlink} ({$nbytes})";
2676 if ( '' != $description && '*' != $description ) {
2677 $sk=$wgUser->getSkin();
2678 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description,$wgTitle) . ')');
2684 function tocIndent($level) {
2685 return str_repeat( '<div class="tocindent">'."\n", $level>0 ?
$level : 0 );
2688 function tocUnindent($level) {
2689 return str_repeat( "</div>\n", $level>0 ?
$level : 0 );
2693 * parameter level defines if we are on an indentation level
2695 function tocLine( $anchor, $tocline, $level ) {
2696 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2700 return '<div class="tocline">'.$link."</div>\n";
2705 function tocTable($toc) {
2706 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2707 # try min-width & co when somebody gets a chance
2708 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2710 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2711 '<b>'.wfMsg('toc').'</b>' .
2713 '</td></tr><tr id="tocinside"><td>'."\n".
2714 $toc."</td></tr></table>\n";
2718 * These two do not check for permissions: check $wgTitle->userCanEdit
2719 * before calling them
2721 function editSectionScript( $section, $head ) {
2722 global $wgTitle, $wgRequest;
2723 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2726 $url = $wgTitle->escapeLocalURL( 'action=edit§ion='.$section );
2727 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2730 function editSectionLink( $section ) {
2732 global $wgTitle, $wgUser, $wgLang;
2734 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2735 # Section edit links would be out of sync on an old page.
2736 # But, if we're diffing to the current page, they'll be
2741 $editurl = '§ion='.$section;
2742 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2744 if( $wgLang->isRTL() ) {
2746 $nearside = 'right';
2751 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2756 * This function is called by EditPage.php and shows a bulletin board style
2757 * toolbar for common editing functions. It can be disabled in the user
2759 * The necessary JavaScript code can be found in style/wikibits.js.
2761 function getEditToolbar() {
2762 global $wgStylePath, $wgLang, $wgMimeType;
2765 * toolarray an array of arrays which each include the filename of
2766 * the button image (without path), the opening tag, the closing tag,
2767 * and optionally a sample text that is inserted between the two when no
2768 * selection is highlighted.
2769 * The tip text is shown when the user moves the mouse over the button.
2771 * Already here are accesskeys (key), which are not used yet until someone
2772 * can figure out a way to make them work in IE. However, we should make
2773 * sure these keys are not defined on the edit page.
2776 array( 'image'=>'button_bold.png',
2778 'close' => "\'\'\'",
2779 'sample'=> wfMsg('bold_sample'),
2780 'tip' => wfMsg('bold_tip'),
2783 array( 'image'=>'button_italic.png',
2786 'sample'=> wfMsg('italic_sample'),
2787 'tip' => wfMsg('italic_tip'),
2790 array( 'image'=>'button_link.png',
2793 'sample'=> wfMsg('link_sample'),
2794 'tip' => wfMsg('link_tip'),
2797 array( 'image'=>'button_extlink.png',
2800 'sample'=> wfMsg('extlink_sample'),
2801 'tip' => wfMsg('extlink_tip'),
2804 array( 'image'=>'button_headline.png',
2806 'close' => " ==\\n",
2807 'sample'=> wfMsg('headline_sample'),
2808 'tip' => wfMsg('headline_tip'),
2811 array( 'image'=>'button_image.png',
2812 'open' => '[['.$wgLang->getNsText(NS_IMAGE
).":",
2814 'sample'=> wfMsg('image_sample'),
2815 'tip' => wfMsg('image_tip'),
2818 array( 'image' => 'button_media.png',
2819 'open' => '[['.$wgLang->getNsText(NS_MEDIA
).':',
2821 'sample'=> wfMsg('media_sample'),
2822 'tip' => wfMsg('media_tip'),
2825 array( 'image' => 'button_math.png',
2826 'open' => "\\<math\\>",
2827 'close' => "\\</math\\>",
2828 'sample'=> wfMsg('math_sample'),
2829 'tip' => wfMsg('math_tip'),
2832 array( 'image' => 'button_nowiki.png',
2833 'open' => "\\<nowiki\\>",
2834 'close' => "\\</nowiki\\>",
2835 'sample'=> wfMsg('nowiki_sample'),
2836 'tip' => wfMsg('nowiki_tip'),
2839 array( 'image' => 'button_sig.png',
2843 'tip' => wfMsg('sig_tip'),
2846 array( 'image' => 'button_hr.png',
2847 'open' => "\\n----\\n",
2850 'tip' => wfMsg('hr_tip'),
2854 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2856 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2857 foreach($toolarray as $tool) {
2859 $image=$wgStylePath.'/common/images/'.$tool['image'];
2860 $open=$tool['open'];
2861 $close=$tool['close'];
2862 $sample = addslashes( $tool['sample'] );
2864 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2865 // Older browsers show a "speedtip" type message only for ALT.
2866 // Ideally these should be different, realistically they
2867 // probably don't need to be.
2868 $tip = addslashes( $tool['tip'] );
2870 #$key = $tool["key"];
2872 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2875 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2876 $toolbar.="document.writeln(\"</div>\");\n";
2878 $toolbar.="/*]]>*/\n</script>";
2885 function suppressUrlExpansion() {