Fixed bug which caused ru.wikipedia to go offline when someone put   in MediaWik...
[lhc/web/wiklou.git] / includes / Skin.php
1 <?php
2
3 # This is not a valid entry point, perform no further processing unless MEDIAWIKI is defined
4 if( defined( "MEDIAWIKI" ) ) {
5
6 # See skin.doc
7
8 require_once( 'Feed.php' ); // should not be called if the actual page isn't feed enabled
9 require_once( 'Image.php' );
10
11 # These are the INTERNAL names, which get mapped
12 # directly to class names. For display purposes, the
13 # Language class has internationalized names
14 #
15 /* private */ $wgValidSkinNames = array(
16 'standard' => 'Standard',
17 'nostalgia' => 'Nostalgia',
18 'cologneblue' => 'CologneBlue'
19 );
20 if( $wgUsePHPTal ) {
21 #$wgValidSkinNames[] = 'PHPTal';
22 #$wgValidSkinNames['davinci'] = 'DaVinci';
23 #$wgValidSkinNames['mono'] = 'Mono';
24 $wgValidSkinNames['monobook'] = 'MonoBook';
25 $wgValidSkinNames['myskin'] = 'MySkin';
26 #$wgValidSkinNames['monobookminimal'] = 'MonoBookMinimal';
27 $wgValidSkinNames['chick'] = 'Chick';
28 }
29
30 require_once( 'RecentChange.php' );
31
32 class RCCacheEntry extends RecentChange
33 {
34 var $secureName, $link;
35 var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
36 var $userlink, $timestamp, $watched;
37
38 function newFromParent( $rc )
39 {
40 $rc2 = new RCCacheEntry;
41 $rc2->mAttribs = $rc->mAttribs;
42 $rc2->mExtra = $rc->mExtra;
43 return $rc2;
44 }
45 } ;
46
47 class Skin {
48
49 /* private */ var $lastdate, $lastline;
50 var $linktrail ; # linktrail regexp
51 var $rc_cache ; # Cache for Enhanced Recent Changes
52 var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle
53 var $rcMoveIndex;
54 var $postParseLinkColour = true;
55
56 function Skin()
57 {
58 global $wgUseOldExistenceCheck;
59 $postParseLinkColour = !$wgUseOldExistenceCheck;
60 $this->linktrail = wfMsg('linktrail');
61 }
62
63 function getSkinNames()
64 {
65 global $wgValidSkinNames;
66 return $wgValidSkinNames;
67 }
68
69 function getStylesheet()
70 {
71 return 'wikistandard.css';
72 }
73 function getSkinName() {
74 return "standard";
75 }
76
77 # Get/set accessor for delayed link colouring
78 function postParseLinkColour( $setting = NULL ) {
79 return wfSetVar( $this->postParseLinkColour, $setting );
80 }
81
82 function qbSetting()
83 {
84 global $wgOut, $wgUser;
85
86 if ( $wgOut->isQuickbarSuppressed() ) { return 0; }
87 $q = $wgUser->getOption( 'quickbar' );
88 if ( '' == $q ) { $q = 0; }
89 return $q;
90 }
91
92 function initPage( &$out )
93 {
94 $fname = 'Skin::initPage';
95 wfProfileIn( $fname );
96
97 $out->addLink( array( 'rel' => 'shortcut icon', 'href' => '/favicon.ico' ) );
98
99 $this->addMetadataLinks($out);
100
101 wfProfileOut( $fname );
102 }
103
104 function addMetadataLinks( &$out ) {
105 global $wgTitle, $wgEnableDublinCoreRdf, $wgEnableCreativeCommonsRdf, $wgRdfMimeType, $action;
106 global $wgRightsPage, $wgRightsUrl;
107
108 if( $out->isArticleRelated() ) {
109 # note: buggy CC software only reads first "meta" link
110 if( $wgEnableCreativeCommonsRdf ) {
111 $out->addMetadataLink( array(
112 'title' => 'Creative Commons',
113 'type' => 'application/rdf+xml',
114 'href' => $wgTitle->getLocalURL( 'action=creativecommons') ) );
115 }
116 if( $wgEnableDublinCoreRdf ) {
117 $out->addMetadataLink( array(
118 'title' => 'Dublin Core',
119 'type' => 'application/rdf+xml',
120 'href' => $wgTitle->getLocalURL( 'action=dublincore' ) ) );
121 }
122 }
123 $copyright = '';
124 if( $wgRightsPage ) {
125 $copy = Title::newFromText( $wgRightsPage );
126 if( $copy ) {
127 $copyright = $copy->getLocalURL();
128 }
129 }
130 if( !$copyright && $wgRightsUrl ) {
131 $copyright = $wgRightsUrl;
132 }
133 if( $copyright ) {
134 $out->addLink( array(
135 'rel' => 'copyright',
136 'href' => $copyright ) );
137 }
138 }
139
140 function outputPage( &$out ) {
141 global $wgDebugComments;
142
143 wfProfileIn( 'Skin::outputPage' );
144 $this->initPage( $out );
145 $out->out( $out->headElement() );
146
147 $out->out( "\n<body" );
148 $ops = $this->getBodyOptions();
149 foreach ( $ops as $name => $val ) {
150 $out->out( " $name='$val'" );
151 }
152 $out->out( ">\n" );
153 if ( $wgDebugComments ) {
154 $out->out( "<!-- Wiki debugging output:\n" .
155 $out->mDebugtext . "-->\n" );
156 }
157 $out->out( $this->beforeContent() );
158
159 $out->out( $out->mBodytext . "\n" );
160
161 $out->out( $this->afterContent() );
162
163 wfProfileClose();
164 $out->out( $out->reportTime() );
165
166 $out->out( "\n</body></html>" );
167 }
168
169 function getHeadScripts() {
170 global $wgStylePath, $wgUser, $wgLang, $wgAllowUserJs;
171 $r = "<script type=\"text/javascript\" src=\"{$wgStylePath}/wikibits.js\"></script>\n";
172 if( $wgAllowUserJs && $wgUser->getID() != 0 ) { # logged in
173 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
174 $userjs = htmlspecialchars($this->makeUrl($userpage.'/'.$this->getSkinName().'.js', 'action=raw&ctype=text/javascript'));
175 $r .= '<script type="text/javascript" src="'.$userjs."\"></script>\n";
176 }
177 return $r;
178 }
179
180 # get the user/site-specific stylesheet, SkinPHPTal called from RawPage.php (settings are cached that way)
181 function getUserStylesheet() {
182 global $wgOut, $wgStylePath, $wgLang, $wgUser, $wgRequest, $wgTitle, $wgAllowUserCss;
183 $sheet = $this->getStylesheet();
184 $action = $wgRequest->getText('action');
185 $s = "@import \"$wgStylePath/$sheet\";\n";
186 if($wgLang->isRTL()) $s .= "@import \"$wgStylePath/common_rtl.css\";\n";
187 if( $wgAllowUserCss && $wgUser->getID() != 0 ) { # logged in
188 if($wgTitle->isCssSubpage() and $action == 'submit' and $wgTitle->userCanEditCssJsSubpage()) {
189 $s .= $wgRequest->getText('wpTextbox1');
190 } else {
191 $userpage = $wgLang->getNsText( Namespace::getUser() ) . ":" . $wgUser->getName();
192 $s.= '@import "'.$this->makeUrl($userpage.'/'.$this->getSkinName().'.css', 'action=raw&ctype=text/css').'";'."\n";
193 }
194 }
195 $s .= $this->doGetUserStyles();
196 return $s."\n";
197 }
198 # placeholder, returns generated js in monobook
199 function getUserJs() {
200 return;
201 }
202
203 function getUserStyles()
204 {
205 global $wgOut, $wgStylePath, $wgLang;
206 $s = "<style type='text/css'>\n";
207 $s .= "/*/*/ /*<![CDATA[*/\n"; # <-- Hide the styles from Netscape 4 without hiding them from IE/Mac
208 $s .= $this->getUserStylesheet();
209 $s .= "/*]]>*/ /* */\n";
210 $s .= "</style>\n";
211 return $s;
212 }
213
214 function doGetUserStyles()
215 {
216 global $wgUser, $wgLang;
217
218 $csspage = $wgLang->getNsText( NS_MEDIAWIKI ) . ":" . $this->getSkinName() . ".css";
219 $s = '@import "'.$this->makeUrl($csspage, 'action=raw&ctype=text/css')."\";\n";
220
221 if ( 1 == $wgUser->getOption( 'underline' ) ) {
222 # Don't override browser settings
223 } else {
224 # CHECK MERGE @@@
225 # Force no underline
226 $s .= "a { text-decoration: none; }\n";
227 }
228 if ( 1 == $wgUser->getOption( 'highlightbroken' ) ) {
229 $s .= "a.new, #quickbar a.new { color: #CC2200; }\n";
230 }
231 if ( 1 == $wgUser->getOption( 'justify' ) ) {
232 $s .= "#article { text-align: justify; }\n";
233 }
234 return $s;
235 }
236
237 function getBodyOptions()
238 {
239 global $wgUser, $wgTitle, $wgNamespaceBackgrounds, $wgOut, $wgRequest;
240
241 extract( $wgRequest->getValues( 'oldid', 'redirect', 'diff' ) );
242
243 if ( 0 != $wgTitle->getNamespace() ) {
244 $a = array( 'bgcolor' => '#ffffec' );
245 }
246 else $a = array( 'bgcolor' => '#FFFFFF' );
247 if($wgOut->isArticle() && $wgUser->getOption('editondblclick') &&
248 (!$wgTitle->isProtected() || $wgUser->isSysop()) ) {
249 $t = wfMsg( 'editthispage' );
250 $oid = $red = '';
251 if ( !empty($redirect) ) {
252 $red = "&redirect={$redirect}";
253 }
254 if ( !empty($oldid) && ! isset( $diff ) ) {
255 $oid = "&oldid={$oldid}";
256 }
257 $s = $wgTitle->getFullURL( "action=edit{$oid}{$red}" );
258 $s = 'document.location = "' .$s .'";';
259 $a += array ('ondblclick' => $s);
260
261 }
262 $a['onload'] = $wgOut->getOnloadHandler();
263 return $a;
264 }
265
266 function getExternalLinkAttributes( $link, $text, $class='' )
267 {
268 global $wgUser, $wgOut, $wgLang;
269
270 $link = urldecode( $link );
271 $link = $wgLang->checkTitleEncoding( $link );
272 $link = str_replace( '_', ' ', $link );
273 $link = htmlspecialchars( $link );
274
275 $r = ($class != '') ? " class='$class'" : " class='external'";
276
277 if ( 1 == $wgUser->getOption( 'hover' ) ) {
278 $r .= " title=\"{$link}\"";
279 }
280 return $r;
281 }
282
283 function getInternalLinkAttributes( $link, $text, $broken = false )
284 {
285 global $wgUser, $wgOut;
286
287 $link = urldecode( $link );
288 $link = str_replace( '_', ' ', $link );
289 $link = htmlspecialchars( $link );
290
291 if ( $broken == 'stub' ) {
292 $r = ' class="stub"';
293 } else if ( $broken == 'yes' ) {
294 $r = ' class="new"';
295 } else {
296 $r = '';
297 }
298
299 if ( 1 == $wgUser->getOption( 'hover' ) ) {
300 $r .= " title=\"{$link}\"";
301 }
302 return $r;
303 }
304
305 function getInternalLinkAttributesObj( &$nt, $text, $broken = false )
306 {
307 global $wgUser, $wgOut;
308
309 if ( $broken == 'stub' ) {
310 $r = ' class="stub"';
311 } else if ( $broken == 'yes' ) {
312 $r = ' class="new"';
313 } else {
314 $r = '';
315 }
316
317 if ( 1 == $wgUser->getOption( 'hover' ) ) {
318 $r .= ' title ="' . $nt->getEscapedText() . '"';
319 }
320 return $r;
321 }
322
323 function getLogo()
324 {
325 global $wgLogo;
326 return $wgLogo;
327 }
328
329 # This will be called immediately after the <body> tag. Split into
330 # two functions to make it easier to subclass.
331 #
332 function beforeContent()
333 {
334 global $wgUser, $wgOut;
335
336 return $this->doBeforeContent();
337 }
338
339 function doBeforeContent()
340 {
341 global $wgUser, $wgOut, $wgTitle, $wgLang, $wgSiteNotice;
342 $fname = 'Skin::doBeforeContent';
343 wfProfileIn( $fname );
344
345 $s = '';
346 $qb = $this->qbSetting();
347
348 if( $langlinks = $this->otherLanguages() ) {
349 $rows = 2;
350 $borderhack = '';
351 } else {
352 $rows = 1;
353 $langlinks = false;
354 $borderhack = 'class="top"';
355 }
356
357 $s .= "\n<div id='content'>\n<div id='topbar'>\n" .
358 "<table border='0' cellspacing='0' width='98%'>\n<tr>\n";
359
360 $shove = ($qb != 0);
361 $left = ($qb == 1 || $qb == 3);
362 if($wgLang->isRTL()) $left = !$left;
363
364 if ( !$shove ) {
365 $s .= "<td class='top' align='left' valign='top' rowspan='{$rows}'>\n" .
366 $this->logoText() . '</td>';
367 } elseif( $left ) {
368 $s .= $this->getQuickbarCompensator( $rows );
369 }
370 $l = $wgLang->isRTL() ? 'right' : 'left';
371 $s .= "<td {$borderhack} align='$l' valign='top'>\n";
372
373 $s .= $this->topLinks() ;
374 $s .= "<p class='subtitle'>" . $this->pageTitleLinks() . "</p>\n";
375
376 $r = $wgLang->isRTL() ? "left" : "right";
377 $s .= "</td>\n<td {$borderhack} valign='top' align='$r' nowrap='nowrap'>";
378 $s .= $this->nameAndLogin();
379 $s .= "\n<br />" . $this->searchForm() . "</td>";
380
381 if ( $langlinks ) {
382 $s .= "</tr>\n<tr>\n<td class='top' colspan=\"2\">$langlinks</td>\n";
383 }
384
385 if ( $shove && !$left ) { # Right
386 $s .= $this->getQuickbarCompensator( $rows );
387 }
388 $s .= "</tr>\n</table>\n</div>\n";
389 $s .= "\n<div id='article'>\n";
390
391 if( $wgSiteNotice ) {
392 $s .= "\n<div id='siteNotice'>$wgSiteNotice</div>\n";
393 }
394 $s .= $this->pageTitle();
395 $s .= $this->pageSubtitle() ;
396 $s .= $this->getCategories();
397 wfProfileOut( $fname );
398 return $s;
399 }
400
401 function getCategoryLinks () {
402 global $wgOut, $wgTitle, $wgUser, $wgParser;
403 global $wgUseCategoryMagic, $wgUseCategoryBrowser, $wgLang;
404
405 if( !$wgUseCategoryMagic ) return '' ;
406 if( count( $wgOut->mCategoryLinks ) == 0 ) return '';
407
408 # Taken out so that they will be displayed in previews -- TS
409 #if( !$wgOut->isArticle() ) return '';
410
411 $t = implode ( ' | ' , $wgOut->mCategoryLinks ) ;
412 $s = $this->makeKnownLink( 'Special:Categories',
413 wfMsg( 'categories' ), 'article=' . urlencode( $wgTitle->getPrefixedDBkey() ) )
414 . ': ' . $t;
415
416 if($wgUseCategoryBrowser) {
417 $s .= '<br/><hr/>';
418 $catstack = array();
419 $s.= $wgTitle->getAllParentCategories($catstack);
420 }
421
422 return $s;
423 }
424
425 function getCategories() {
426 $catlinks=$this->getCategoryLinks();
427 if(!empty($catlinks)) {
428 return "<p class='catlinks'>{$catlinks}</p>";
429 }
430 }
431
432 function getQuickbarCompensator( $rows = 1 )
433 {
434 return "<td width='152' rowspan='{$rows}'>&nbsp;</td>";
435 }
436
437 # This gets called immediately before the </body> tag.
438 #
439 function afterContent()
440 {
441 global $wgUser, $wgOut, $wgServer;
442 global $wgTitle, $wgLang;
443
444 $printfooter = "<div class=\"printfooter\">\n" . $this->printFooter() . "</div>\n";
445 return $printfooter . $this->doAfterContent();
446 }
447
448 function printSource() {
449 global $wgTitle;
450 $url = htmlspecialchars( $wgTitle->getFullURL() );
451 return wfMsg( "retrievedfrom", "<a href=\"$url\">$url</a>" );
452 }
453
454 function printFooter() {
455 return "<p>" . $this->printSource() .
456 "</p>\n\n<p>" . $this->pageStats() . "</p>\n";
457 }
458
459 function doAfterContent()
460 {
461 global $wgUser, $wgOut, $wgLang;
462 $fname = 'Skin::doAfterContent';
463 wfProfileIn( $fname );
464 wfProfileIn( $fname.'-1' );
465
466 $s = "\n</div><br style=\"clear:both\" />\n";
467 $s .= "\n<div id='footer'>";
468 $s .= '<table border="0" cellspacing="0"><tr>';
469
470 wfProfileOut( $fname.'-1' );
471 wfProfileIn( $fname.'-2' );
472
473 $qb = $this->qbSetting();
474 $shove = ($qb != 0);
475 $left = ($qb == 1 || $qb == 3);
476 if($wgLang->isRTL()) $left = !$left;
477
478 if ( $shove && $left ) { # Left
479 $s .= $this->getQuickbarCompensator();
480 }
481 wfProfileOut( $fname.'-2' );
482 wfProfileIn( $fname.'-3' );
483 $l = $wgLang->isRTL() ? 'right' : 'left';
484 $s .= "<td class='bottom' align='$l' valign='top'>";
485
486 $s .= $this->bottomLinks();
487 $s .= "\n<br />" . $this->mainPageLink()
488 . ' | ' . $this->aboutLink()
489 . ' | ' . $this->specialLink( 'recentchanges' )
490 . ' | ' . $this->searchForm()
491 . '<br /><span id="pagestats">' . $this->pageStats() . '</span>';
492
493 $s .= "</td>";
494 if ( $shove && !$left ) { # Right
495 $s .= $this->getQuickbarCompensator();
496 }
497 $s .= "</tr></table>\n</div>\n</div>\n";
498
499 wfProfileOut( $fname.'-3' );
500 wfProfileIn( $fname.'-4' );
501 if ( 0 != $qb ) { $s .= $this->quickBar(); }
502 wfProfileOut( $fname.'-4' );
503 wfProfileOut( $fname );
504 return $s;
505 }
506
507 function pageTitleLinks()
508 {
509 global $wgOut, $wgTitle, $wgUser, $wgLang, $wgUseApproval, $wgRequest;
510
511 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
512 $action = $wgRequest->getText( 'action' );
513
514 $s = $this->printableLink();
515 if ( wfMsg ( 'disclaimers' ) != '-' ) $s .= ' | ' . $this->makeKnownLink( wfMsg( 'disclaimerpage' ), wfMsg( 'disclaimers' ) ) ;
516
517 if ( $wgOut->isArticleRelated() ) {
518 if ( $wgTitle->getNamespace() == Namespace::getImage() ) {
519 $name = $wgTitle->getDBkey();
520 $link = htmlspecialchars( Image::wfImageUrl( $name ) );
521 $style = $this->getInternalLinkAttributes( $link, $name );
522 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>";
523 }
524 # This will show the "Approve" link if $wgUseApproval=true;
525 if ( isset ( $wgUseApproval ) && $wgUseApproval )
526 {
527 $t = $wgTitle->getDBkey();
528 $name = 'Approve this article' ;
529 $link = "http://test.wikipedia.org/w/magnus/wiki.phtml?title={$t}&action=submit&doit=1" ;
530 #htmlspecialchars( wfImageUrl( $name ) );
531 $style = $this->getExternalLinkAttributes( $link, $name );
532 $s .= " | <a href=\"{$link}\"{$style}>{$name}</a>" ;
533 }
534 }
535 if ( 'history' == $action || isset( $diff ) || isset( $oldid ) ) {
536 $s .= ' | ' . $this->makeKnownLink( $wgTitle->getPrefixedText(),
537 wfMsg( 'currentrev' ) );
538 }
539
540 if ( $wgUser->getNewtalk() ) {
541 # do not show "You have new messages" text when we are viewing our
542 # own talk page
543
544 if(!(strcmp($wgTitle->getText(),$wgUser->getName()) == 0 &&
545 $wgTitle->getNamespace()==Namespace::getTalk(Namespace::getUser()))) {
546 $n =$wgUser->getName();
547 $tl = $this->makeKnownLink( $wgLang->getNsText(
548 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
549 wfMsg('newmessageslink') );
550 $s.= ' | <strong>'. wfMsg( 'newmessages', $tl ) . '</strong>';
551 }
552 }
553
554 $undelete = $this->getUndeleteLink();
555 if( !empty( $undelete ) ) {
556 $s .= ' | '.$undelete;
557 }
558 return $s;
559 }
560
561 function getUndeleteLink() {
562 global $wgUser, $wgTitle, $wgLang, $action;
563 if( $wgUser->isSysop() &&
564 (($wgTitle->getArticleId() == 0) || ($action == "history")) &&
565 ($n = $wgTitle->isDeleted() ) ) {
566 return wfMsg( 'thisisdeleted',
567 $this->makeKnownLink(
568 $wgLang->SpecialPage( 'Undelete/' . $wgTitle->getPrefixedDBkey() ),
569 wfMsg( 'restorelink', $n ) ) );
570 }
571 return '';
572 }
573
574 function printableLink()
575 {
576 global $wgOut, $wgFeedClasses, $wgRequest;
577
578 $baseurl = $_SERVER['REQUEST_URI'];
579 if( strpos( '?', $baseurl ) == false ) {
580 $baseurl .= '?';
581 } else {
582 $baseurl .= '&';
583 }
584 $baseurl = htmlspecialchars( $baseurl );
585 $printurl = $wgRequest->escapeAppendQuery( 'printable=yes' );
586
587 $s = "<a href=\"$printurl\">" . wfMsg( 'printableversion' ) . '</a>';
588 if( $wgOut->isSyndicated() ) {
589 foreach( $wgFeedClasses as $format => $class ) {
590 $feedurl = $wgRequest->escapeAppendQuery( "feed=$format" );
591 $s .= " | <a href=\"$feedurl\">{$format}</a>";
592 }
593 }
594 return $s;
595 }
596
597 function pageTitle()
598 {
599 global $wgOut, $wgTitle, $wgUser;
600
601 $s = '<h1 class="pagetitle">' . htmlspecialchars( $wgOut->getPageTitle() ) . '</h1>';
602 if($wgUser->getOption( 'editsectiononrightclick' ) && $wgTitle->userCanEdit()) { $s=$this->editSectionScript(0,$s);}
603 return $s;
604 }
605
606 function pageSubtitle()
607 {
608 global $wgOut;
609
610 $sub = $wgOut->getSubtitle();
611 if ( '' == $sub ) {
612 global $wgExtraSubtitle;
613 $sub = wfMsg( 'fromwikipedia' ) . $wgExtraSubtitle;
614 }
615 $subpages = $this->subPageSubtitle();
616 $sub .= !empty($subpages)?"</p><p class='subpages'>$subpages":'';
617 $s = "<p class='subtitle'>{$sub}</p>\n";
618 return $s;
619 }
620
621 function subPageSubtitle()
622 {
623 global $wgOut,$wgTitle,$wgNamespacesWithSubpages;
624 $subpages = '';
625 if($wgOut->isArticle() && !empty($wgNamespacesWithSubpages[$wgTitle->getNamespace()])) {
626 $ptext=$wgTitle->getPrefixedText();
627 if(preg_match('/\//',$ptext)) {
628 $links = explode('/',$ptext);
629 $c = 0;
630 $growinglink = '';
631 foreach($links as $link) {
632 $c++;
633 if ($c<count($links)) {
634 $growinglink .= $link;
635 $getlink = $this->makeLink( $growinglink, $link );
636 if(preg_match('/class="new"/i',$getlink)) { break; } # this is a hack, but it saves time
637 if ($c>1) {
638 $subpages .= ' | ';
639 } else {
640 $subpages .= '&lt; ';
641 }
642 $subpages .= $getlink;
643 $growinglink .= '/';
644 }
645 }
646 }
647 }
648 return $subpages;
649 }
650
651 function nameAndLogin()
652 {
653 global $wgUser, $wgTitle, $wgLang, $wgShowIPinHeader, $wgIP;
654
655 $li = $wgLang->specialPage( 'Userlogin' );
656 $lo = $wgLang->specialPage( 'Userlogout' );
657
658 $s = '';
659 if ( 0 == $wgUser->getID() ) {
660 if( $wgShowIPinHeader && isset( $_COOKIE[ini_get('session.name')] ) ) {
661 $n = $wgIP;
662
663 $tl = $this->makeKnownLink( $wgLang->getNsText(
664 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
665 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
666
667 $s .= $n . ' ('.$tl.')';
668 } else {
669 $s .= wfMsg('notloggedin');
670 }
671
672 $rt = $wgTitle->getPrefixedURL();
673 if ( 0 == strcasecmp( urlencode( $lo ), $rt ) ) {
674 $q = '';
675 } else { $q = "returnto={$rt}"; }
676
677 $s .= "\n<br />" . $this->makeKnownLink( $li,
678 wfMsg( 'login' ), $q );
679 } else {
680 $n = $wgUser->getName();
681 $rt = $wgTitle->getPrefixedURL();
682 $tl = $this->makeKnownLink( $wgLang->getNsText(
683 Namespace::getTalk( Namespace::getUser() ) ) . ":{$n}",
684 $wgLang->getNsText( Namespace::getTalk( 0 ) ) );
685
686 $tl = " ({$tl})";
687
688 $s .= $this->makeKnownLink( $wgLang->getNsText(
689 Namespace::getUser() ) . ":{$n}", $n ) . "{$tl}<br />" .
690 $this->makeKnownLink( $lo, wfMsg( 'logout' ),
691 "returnto={$rt}" ) . ' | ' .
692 $this->specialLink( 'preferences' );
693 }
694 $s .= ' | ' . $this->makeKnownLink( wfMsg( 'helppage' ),
695 wfMsg( 'help' ) );
696
697 return $s;
698 }
699
700 function getSearchLink() {
701 $searchPage =& Title::makeTitle( NS_SPECIAL, 'Search' );
702 return $searchPage->getLocalURL();
703 }
704
705 function escapeSearchLink() {
706 return htmlspecialchars( $this->getSearchLink() );
707 }
708
709 function searchForm()
710 {
711 global $wgRequest;
712 $search = $wgRequest->getText( 'search' );
713
714 $s = '<form name="search" class="inline" method="post" action="'
715 . $this->escapeSearchLink() . "\">\n"
716 . '<input type="text" name="search" size="19" value="'
717 . htmlspecialchars(substr($search,0,256)) . "\" />\n"
718 . '<input type="submit" name="go" value="' . wfMsg ('go') . '" />&nbsp;'
719 . '<input type="submit" name="fulltext" value="' . wfMsg ('search') . "\" />\n</form>";
720
721 return $s;
722 }
723
724 function topLinks()
725 {
726 global $wgOut;
727 $sep = " |\n";
728
729 $s = $this->mainPageLink() . $sep
730 . $this->specialLink( 'recentchanges' );
731
732 if ( $wgOut->isArticleRelated() ) {
733 $s .= $sep . $this->editThisPage()
734 . $sep . $this->historyLink();
735 }
736 # Many people don't like this dropdown box
737 #$s .= $sep . $this->specialPagesList();
738
739 return $s;
740 }
741
742 function bottomLinks()
743 {
744 global $wgOut, $wgUser, $wgTitle;
745 $sep = " |\n";
746
747 $s = '';
748 if ( $wgOut->isArticleRelated() ) {
749 $s .= '<strong>' . $this->editThisPage() . '</strong>';
750 if ( 0 != $wgUser->getID() ) {
751 $s .= $sep . $this->watchThisPage();
752 }
753 $s .= $sep . $this->talkLink()
754 . $sep . $this->historyLink()
755 . $sep . $this->whatLinksHere()
756 . $sep . $this->watchPageLinksLink();
757
758 if ( $wgTitle->getNamespace() == Namespace::getUser()
759 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser()) )
760
761 {
762 $id=User::idFromName($wgTitle->getText());
763 $ip=User::isIP($wgTitle->getText());
764
765 if($id || $ip) { # both anons and non-anons have contri list
766 $s .= $sep . $this->userContribsLink();
767 }
768 if ( 0 != $wgUser->getID() ) { # show only to signed in users
769 if($id) { # can only email non-anons
770 $s .= $sep . $this->emailUserLink();
771 }
772 }
773 }
774 if ( $wgUser->isSysop() && $wgTitle->getArticleId() ) {
775 $s .= "\n<br />" . $this->deleteThisPage() .
776 $sep . $this->protectThisPage() .
777 $sep . $this->moveThisPage();
778 }
779 $s .= "<br />\n" . $this->otherLanguages();
780 }
781 return $s;
782 }
783
784 function pageStats()
785 {
786 global $wgOut, $wgLang, $wgArticle, $wgRequest;
787 global $wgDisableCounters, $wgMaxCredits, $wgShowCreditsIfMax;
788
789 extract( $wgRequest->getValues( 'oldid', 'diff' ) );
790 if ( ! $wgOut->isArticle() ) { return ''; }
791 if ( isset( $oldid ) || isset( $diff ) ) { return ''; }
792 if ( 0 == $wgArticle->getID() ) { return ''; }
793
794 $s = '';
795 if ( !$wgDisableCounters ) {
796 $count = $wgLang->formatNum( $wgArticle->getCount() );
797 if ( $count ) {
798 $s = wfMsg( 'viewcount', $count );
799 }
800 }
801
802 if (isset($wgMaxCredits) && $wgMaxCredits != 0) {
803 require_once("Credits.php");
804 $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax);
805 } else {
806 $s .= $this->lastModified();
807 }
808
809 return $s . ' ' . $this->getCopyright();
810 }
811
812 function getCopyright() {
813 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRequest;
814
815
816 $oldid = $wgRequest->getVal( 'oldid' );
817 $diff = $wgRequest->getVal( 'diff' );
818
819 if ( !is_null( $oldid ) && is_null( $diff ) && wfMsg( 'history_copyright' ) !== '-' ) {
820 $msg = 'history_copyright';
821 } else {
822 $msg = 'copyright';
823 }
824
825 $out = '';
826 if( $wgRightsPage ) {
827 $link = $this->makeKnownLink( $wgRightsPage, $wgRightsText );
828 } elseif( $wgRightsUrl ) {
829 $link = $this->makeExternalLink( $wgRightsUrl, $wgRightsText );
830 } else {
831 # Give up now
832 return $out;
833 }
834 $out .= wfMsg( $msg, $link );
835 return $out;
836 }
837
838 function getCopyrightIcon() {
839 global $wgRightsPage, $wgRightsUrl, $wgRightsText, $wgRightsIcon;
840 $out = '';
841 if( $wgRightsIcon ) {
842 $icon = htmlspecialchars( $wgRightsIcon );
843 if( $wgRightsUrl ) {
844 $url = htmlspecialchars( $wgRightsUrl );
845 $out .= '<a href="'.$url.'">';
846 }
847 $text = htmlspecialchars( $wgRightsText );
848 $out .= "<img src=\"$icon\" alt='$text' />";
849 if( $wgRightsUrl ) {
850 $out .= '</a>';
851 }
852 }
853 return $out;
854 }
855
856 function getPoweredBy() {
857 global $wgStylePath;
858 $url = htmlspecialchars( "$wgStylePath/images/poweredby_mediawiki_88x31.png" );
859 $img = '<a href="http://www.mediawiki.org/"><img src="'.$url.'" alt="MediaWiki" /></a>';
860 return $img;
861 }
862
863 function lastModified()
864 {
865 global $wgLang, $wgArticle;
866
867 $timestamp = $wgArticle->getTimestamp();
868 if ( $timestamp ) {
869 $d = $wgLang->timeanddate( $wgArticle->getTimestamp(), true );
870 $s = ' ' . wfMsg( 'lastmodified', $d );
871 } else {
872 $s = '';
873 }
874 return $s;
875 }
876
877 function logoText( $align = '' )
878 {
879 if ( '' != $align ) { $a = ' align="'.$align.'"'; }
880 else { $a = ''; }
881
882 $mp = wfMsg( 'mainpage' );
883 $titleObj = Title::newFromText( $mp );
884 if ( is_object( $titleObj ) ) {
885 $url = $titleObj->escapeLocalURL();
886 } else {
887 $url = '';
888 }
889
890 $s = '<a href="' . $url
891 . '"><img'.$a.' src="'
892 . $this->getLogo() . '" alt="' . "[{$mp}]\" /></a>";
893 return $s;
894 }
895
896 function quickBar()
897 {
898 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
899 global $wgDisableUploads, $wgRemoteUploads;
900
901 $fname = 'Skin::quickBar';
902 wfProfileIn( $fname );
903
904 $action = $wgRequest->getText( 'action' );
905 $wpPreview = $wgRequest->getBool( 'wpPreview' );
906 $tns=$wgTitle->getNamespace();
907
908 $s = "\n<div id='quickbar'>";
909 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
910
911 $sep = "\n<br />";
912 $s .= $this->mainPageLink()
913 . $sep . $this->specialLink( 'recentchanges' )
914 . $sep . $this->specialLink( 'randompage' );
915 if ($wgUser->getID()) {
916 $s.= $sep . $this->specialLink( 'watchlist' ) ;
917 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
918 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
919
920 }
921 // only show watchlist link if logged in
922 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
923 $s .= "\n<br /><hr class='sep' />";
924 $articleExists = $wgTitle->getArticleId();
925 if ( $wgOut->isArticle() || $action =='edit' || $action =='history' || $wpPreview) {
926 if($wgOut->isArticle()) {
927 $s .= '<strong>' . $this->editThisPage() . '</strong>';
928 } else { # backlink to the article in edit or history mode
929 if($articleExists){ # no backlink if no article
930 switch($tns) {
931 case 0:
932 $text = wfMsg('articlepage');
933 break;
934 case 1:
935 $text = wfMsg('viewtalkpage');
936 break;
937 case 2:
938 $text = wfMsg('userpage');
939 break;
940 case 3:
941 $text = wfMsg('viewtalkpage');
942 break;
943 case 4:
944 $text = wfMsg('wikipediapage');
945 break;
946 case 5:
947 $text = wfMsg('viewtalkpage');
948 break;
949 case 6:
950 $text = wfMsg('imagepage');
951 break;
952 case 7:
953 $text = wfMsg('viewtalkpage');
954 break;
955 default:
956 $text= wfMsg('articlepage');
957 }
958
959 $link = $wgTitle->getText();
960 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
961 $link = $nstext . ':' . $link ;
962 }
963
964 $s .= $this->makeLink( $link, $text );
965 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
966 # we just throw in a "New page" text to tell the user that he's in edit mode,
967 # and to avoid messing with the separator that is prepended to the next item
968 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
969 }
970
971 }
972
973
974 if( $tns%2 && $action!='edit' && !$wpPreview) {
975 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit&section=new');
976 }
977
978 /*
979 watching could cause problems in edit mode:
980 if user edits article, then loads "watch this article" in background and then saves
981 article with "Watch this article" checkbox disabled, the article is transparently
982 unwatched. Therefore we do not show the "Watch this page" link in edit mode
983 */
984 if ( 0 != $wgUser->getID() && $articleExists) {
985 if($action!='edit' && $action != 'submit' )
986 {
987 $s .= $sep . $this->watchThisPage();
988 }
989 if ( $wgTitle->userCanEdit() )
990 $s .= $sep . $this->moveThisPage();
991 }
992 if ( $wgUser->isSysop() and $articleExists ) {
993 $s .= $sep . $this->deleteThisPage() .
994 $sep . $this->protectThisPage();
995 }
996 $s .= $sep . $this->talkLink();
997 if ($articleExists && $action !='history') {
998 $s .= $sep . $this->historyLink();
999 }
1000 $s.=$sep . $this->whatLinksHere();
1001
1002 if($wgOut->isArticleRelated()) {
1003 $s .= $sep . $this->watchPageLinksLink();
1004 }
1005
1006 if ( Namespace::getUser() == $wgTitle->getNamespace()
1007 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1008 ) {
1009
1010 $id=User::idFromName($wgTitle->getText());
1011 $ip=User::isIP($wgTitle->getText());
1012
1013 if($id||$ip) {
1014 $s .= $sep . $this->userContribsLink();
1015 }
1016 if ( 0 != $wgUser->getID() ) {
1017 if($id) { # can only email real users
1018 $s .= $sep . $this->emailUserLink();
1019 }
1020 }
1021 }
1022 $s .= "\n<br /><hr class='sep' />";
1023 }
1024
1025 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
1026 $s .= $this->specialLink( 'upload' ) . $sep;
1027 }
1028 $s .= $this->specialLink( 'specialpages' )
1029 . $sep . $this->bugReportsLink();
1030
1031 global $wgSiteSupportPage;
1032 if( $wgSiteSupportPage ) {
1033 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1034 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1035 }
1036
1037 $s .= "\n<br /></div>\n";
1038 wfProfileOut( $fname );
1039 return $s;
1040 }
1041
1042 function specialPagesList()
1043 {
1044 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1045 require_once('SpecialPage.php');
1046 $a = array();
1047 $pages = SpecialPage::getPages();
1048
1049 foreach ( $pages[''] as $name => $page ) {
1050 $a[$name] = $page->getDescription();
1051 }
1052 if ( $wgUser->isSysop() )
1053 {
1054 foreach ( $pages['sysop'] as $name => $page ) {
1055 $a[$name] = $page->getDescription();
1056 }
1057 }
1058 if ( $wgUser->isDeveloper() )
1059 {
1060 foreach ( $pages['developer'] as $name => $page ) {
1061 $a[$name] = $page->getDescription() ;
1062 }
1063 }
1064 $go = wfMsg( 'go' );
1065 $sp = wfMsg( 'specialpages' );
1066 $spp = $wgLang->specialPage( 'Specialpages' );
1067
1068 $s = '<form id="specialpages" method="get" class="inline" ' .
1069 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1070 $s .= "<select name=\"wpDropdown\">\n";
1071 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1072
1073 foreach ( $a as $name => $desc ) {
1074 $p = $wgLang->specialPage( $name );
1075 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1076 }
1077 $s .= "</select>\n";
1078 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1079 $s .= "</form>\n";
1080 return $s;
1081 }
1082
1083 function mainPageLink()
1084 {
1085 $mp = wfMsg( 'mainpage' );
1086 $s = $this->makeKnownLink( $mp, $mp );
1087 return $s;
1088 }
1089
1090 function copyrightLink()
1091 {
1092 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1093 wfMsg( 'copyrightpagename' ) );
1094 return $s;
1095 }
1096
1097 function aboutLink()
1098 {
1099 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1100 wfMsg( 'aboutwikipedia' ) );
1101 return $s;
1102 }
1103
1104
1105 function disclaimerLink()
1106 {
1107 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1108 wfMsg( 'disclaimers' ) );
1109 return $s;
1110 }
1111
1112 function editThisPage()
1113 {
1114 global $wgOut, $wgTitle, $wgRequest;
1115
1116 $oldid = $wgRequest->getVal( 'oldid' );
1117 $diff = $wgRequest->getVal( 'diff' );
1118 $redirect = $wgRequest->getVal( 'redirect' );
1119
1120 if ( ! $wgOut->isArticleRelated() ) {
1121 $s = wfMsg( 'protectedpage' );
1122 } else {
1123 $n = $wgTitle->getPrefixedText();
1124 if ( $wgTitle->userCanEdit() ) {
1125 $t = wfMsg( 'editthispage' );
1126 } else {
1127 #$t = wfMsg( "protectedpage" );
1128 $t = wfMsg( 'viewsource' );
1129 }
1130 $oid = $red = '';
1131
1132 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1133 if ( $oldid && ! isset( $diff ) ) {
1134 $oid = "&oldid={$oldid}";
1135 }
1136 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1137 }
1138 return $s;
1139 }
1140
1141 function deleteThisPage()
1142 {
1143 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1144
1145 $diff = $wgRequest->getVal( 'diff' );
1146 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1147 $n = $wgTitle->getPrefixedText();
1148 $t = wfMsg( 'deletethispage' );
1149
1150 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1151 } else {
1152 $s = '';
1153 }
1154 return $s;
1155 }
1156
1157 function protectThisPage()
1158 {
1159 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1160
1161 $diff = $wgRequest->getVal( 'diff' );
1162 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1163 $n = $wgTitle->getPrefixedText();
1164
1165 if ( $wgTitle->isProtected() ) {
1166 $t = wfMsg( 'unprotectthispage' );
1167 $q = 'action=unprotect';
1168 } else {
1169 $t = wfMsg( 'protectthispage' );
1170 $q = 'action=protect';
1171 }
1172 $s = $this->makeKnownLink( $n, $t, $q );
1173 } else {
1174 $s = '';
1175 }
1176 return $s;
1177 }
1178
1179 function watchThisPage()
1180 {
1181 global $wgUser, $wgOut, $wgTitle;
1182
1183 if ( $wgOut->isArticleRelated() ) {
1184 $n = $wgTitle->getPrefixedText();
1185
1186 if ( $wgTitle->userIsWatching() ) {
1187 $t = wfMsg( 'unwatchthispage' );
1188 $q = 'action=unwatch';
1189 } else {
1190 $t = wfMsg( 'watchthispage' );
1191 $q = 'action=watch';
1192 }
1193 $s = $this->makeKnownLink( $n, $t, $q );
1194 } else {
1195 $s = wfMsg( 'notanarticle' );
1196 }
1197 return $s;
1198 }
1199
1200 function moveThisPage()
1201 {
1202 global $wgTitle, $wgLang;
1203
1204 if ( $wgTitle->userCanEdit() ) {
1205 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1206 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1207 } // no message if page is protected - would be redundant
1208 return $s;
1209 }
1210
1211 function historyLink()
1212 {
1213 global $wgTitle;
1214
1215 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1216 wfMsg( 'history' ), 'action=history' );
1217 return $s;
1218 }
1219
1220 function whatLinksHere()
1221 {
1222 global $wgTitle, $wgLang;
1223
1224 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1225 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1226 return $s;
1227 }
1228
1229 function userContribsLink()
1230 {
1231 global $wgTitle, $wgLang;
1232
1233 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1234 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1235 return $s;
1236 }
1237
1238 function emailUserLink()
1239 {
1240 global $wgTitle, $wgLang;
1241
1242 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1243 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1244 return $s;
1245 }
1246
1247 function watchPageLinksLink()
1248 {
1249 global $wgOut, $wgTitle, $wgLang;
1250
1251 if ( ! $wgOut->isArticleRelated() ) {
1252 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1253 } else {
1254 $s = $this->makeKnownLink( $wgLang->specialPage(
1255 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1256 'target=' . $wgTitle->getPrefixedURL() );
1257 }
1258 return $s;
1259 }
1260
1261 function otherLanguages()
1262 {
1263 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1264
1265 $a = $wgOut->getLanguageLinks();
1266 if ( 0 == count( $a ) ) {
1267 if ( !$wgUseNewInterlanguage ) return '';
1268 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1269 if ( $ns != 0 AND $ns != 1 ) return '' ;
1270 $pn = 'Intl' ;
1271 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1272 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1273 wfMsg( 'intl' ) , $x );
1274 }
1275
1276 if ( !$wgUseNewInterlanguage ) {
1277 $s = wfMsg( 'otherlanguages' ) . ': ';
1278 } else {
1279 global $wgLanguageCode ;
1280 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1281 $x .= '&xl='.$wgLanguageCode ;
1282 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1283 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1284 }
1285
1286 $s = wfMsg( 'otherlanguages' ) . ': ';
1287 $first = true;
1288 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1289 foreach( $a as $l ) {
1290 if ( ! $first ) { $s .= ' | '; }
1291 $first = false;
1292
1293 $nt = Title::newFromText( $l );
1294 $url = $nt->getFullURL();
1295 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1296
1297 if ( '' == $text ) { $text = $l; }
1298 $style = $this->getExternalLinkAttributes( $l, $text );
1299 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1300 }
1301 if($wgLang->isRTL()) $s .= '</span>';
1302 return $s;
1303 }
1304
1305 function bugReportsLink()
1306 {
1307 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1308 wfMsg( 'bugreports' ) );
1309 return $s;
1310 }
1311
1312 function dateLink()
1313 {
1314 global $wgLinkCache;
1315 $t1 = Title::newFromText( gmdate( 'F j' ) );
1316 $t2 = Title::newFromText( gmdate( 'Y' ) );
1317
1318 $wgLinkCache->suspend();
1319 $id = $t1->getArticleID();
1320 $wgLinkCache->resume();
1321
1322 if ( 0 == $id ) {
1323 $s = $this->makeBrokenLink( $t1->getText() );
1324 } else {
1325 $s = $this->makeKnownLink( $t1->getText() );
1326 }
1327 $s .= ', ';
1328
1329 $wgLinkCache->suspend();
1330 $id = $t2->getArticleID();
1331 $wgLinkCache->resume();
1332
1333 if ( 0 == $id ) {
1334 $s .= $this->makeBrokenLink( $t2->getText() );
1335 } else {
1336 $s .= $this->makeKnownLink( $t2->getText() );
1337 }
1338 return $s;
1339 }
1340
1341 function talkLink()
1342 {
1343 global $wgLang, $wgTitle, $wgLinkCache;
1344
1345 $tns = $wgTitle->getNamespace();
1346 if ( -1 == $tns ) { return ''; }
1347
1348 $pn = $wgTitle->getText();
1349 $tp = wfMsg( 'talkpage' );
1350 if ( Namespace::isTalk( $tns ) ) {
1351 $lns = Namespace::getSubject( $tns );
1352 switch($tns) {
1353 case 1:
1354 $text = wfMsg('articlepage');
1355 break;
1356 case 3:
1357 $text = wfMsg('userpage');
1358 break;
1359 case 5:
1360 $text = wfMsg('wikipediapage');
1361 break;
1362 case 7:
1363 $text = wfMsg('imagepage');
1364 break;
1365 default:
1366 $text= wfMsg('articlepage');
1367 }
1368 } else {
1369
1370 $lns = Namespace::getTalk( $tns );
1371 $text=$tp;
1372 }
1373 $n = $wgLang->getNsText( $lns );
1374 if ( '' == $n ) { $link = $pn; }
1375 else { $link = $n.':'.$pn; }
1376
1377 $wgLinkCache->suspend();
1378 $s = $this->makeLink( $link, $text );
1379 $wgLinkCache->resume();
1380
1381 return $s;
1382 }
1383
1384 function commentLink()
1385 {
1386 global $wgLang, $wgTitle, $wgLinkCache;
1387
1388 $tns = $wgTitle->getNamespace();
1389 if ( -1 == $tns ) { return ''; }
1390
1391 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1392
1393 # assert Namespace::isTalk( $lns )
1394
1395 $n = $wgLang->getNsText( $lns );
1396 $pn = $wgTitle->getText();
1397
1398 $link = $n.':'.$pn;
1399
1400 $wgLinkCache->suspend();
1401 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit&section=new');
1402 $wgLinkCache->resume();
1403
1404 return $s;
1405 }
1406
1407 # After all the page content is transformed into HTML, it makes
1408 # a final pass through here for things like table backgrounds.
1409 #
1410 function transformContent( $text )
1411 {
1412 return $text;
1413 }
1414
1415 # Note: This function MUST call getArticleID() on the link,
1416 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1417 #
1418 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1419 wfProfileIn( 'Skin::makeLink' );
1420 $nt = Title::newFromText( $title );
1421 if ($nt) {
1422 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1423 } else {
1424 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1425 $result = $text == "" ? $title : $text;
1426 }
1427
1428 wfProfileOut( 'Skin::makeLink' );
1429 return $result;
1430 }
1431
1432 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1433 $nt = Title::newFromText( $title );
1434 if ($nt) {
1435 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1436 } else {
1437 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1438 return $text == '' ? $title : $text;
1439 }
1440 }
1441
1442 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1443 $nt = Title::newFromText( $title );
1444 if ($nt) {
1445 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1446 } else {
1447 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1448 return $text == '' ? $title : $text;
1449 }
1450 }
1451
1452 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1453 $nt = Title::newFromText( $title );
1454 if ($nt) {
1455 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1456 } else {
1457 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1458 return $text == '' ? $title : $text;
1459 }
1460 }
1461
1462 # Pass a title object, not a title string
1463 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1464 {
1465 global $wgOut, $wgUser;
1466 $fname = 'Skin::makeLinkObj';
1467
1468 # Fail gracefully
1469 if ( ! isset($nt) )
1470 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1471
1472 if ( $nt->isExternal() ) {
1473 $u = $nt->getFullURL();
1474 $link = $nt->getPrefixedURL();
1475 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1476 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1477
1478 $inside = '';
1479 if ( '' != $trail ) {
1480 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1481 $inside = $m[1];
1482 $trail = $m[2];
1483 }
1484 }
1485 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1486 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1487 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1488 } elseif ( ( -1 == $nt->getNamespace() ) ||
1489 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1490 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1491 } else {
1492 if ( $this->postParseLinkColour() ) {
1493 $inside = '';
1494 if ( '' != $trail ) {
1495 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1496 $inside = $m[1];
1497 $trail = $m[2];
1498 }
1499 }
1500
1501 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1502 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1503 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1504 } else {
1505 # Work out link colour immediately
1506 $aid = $nt->getArticleID() ;
1507 if ( 0 == $aid ) {
1508 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1509 } else {
1510 $threshold = $wgUser->getOption('stubthreshold') ;
1511 if ( $threshold > 0 ) {
1512 $dbr =& wfGetDB( DB_SLAVE );
1513 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1514 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1515 if ( $s !== false ) {
1516 $size = $s->x;
1517 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1518 $size = $threshold*2 ; # Really big
1519 }
1520 $dbr->freeResult( $res );
1521 } else {
1522 $size = $threshold*2 ; # Really big
1523 }
1524 } else {
1525 $size = 1 ;
1526 }
1527 if ( $size < $threshold ) {
1528 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1529 } else {
1530 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1531 }
1532 }
1533 }
1534 }
1535 return $retVal;
1536 }
1537
1538 # Pass a title object, not a title string
1539 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1540 {
1541 global $wgOut, $wgTitle, $wgInputEncoding;
1542
1543 $fname = 'Skin::makeKnownLinkObj';
1544 wfProfileIn( $fname );
1545
1546 if ( !is_object( $nt ) ) {
1547 return $text;
1548 }
1549 $link = $nt->getPrefixedURL();
1550
1551 if ( '' == $link ) {
1552 $u = '';
1553 if ( '' == $text ) {
1554 $text = htmlspecialchars( $nt->getFragment() );
1555 }
1556 } else {
1557 $u = $nt->escapeLocalURL( $query );
1558 }
1559 if ( '' != $nt->getFragment() ) {
1560 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT, $wgInputEncoding ) );
1561 $replacearray = array(
1562 '%3A' => ':',
1563 '%' => '.'
1564 );
1565 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1566 }
1567 if ( '' == $text ) {
1568 $text = htmlspecialchars( $nt->getPrefixedText() );
1569 }
1570 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1571
1572 $inside = '';
1573 if ( '' != $trail ) {
1574 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1575 $inside = $m[1];
1576 $trail = $m[2];
1577 }
1578 }
1579 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1580 wfProfileOut( $fname );
1581 return $r;
1582 }
1583
1584 # Pass a title object, not a title string
1585 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1586 {
1587 global $wgOut, $wgUser;
1588
1589 # Fail gracefully
1590 if ( ! isset($nt) )
1591 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1592
1593 $fname = 'Skin::makeBrokenLinkObj';
1594 wfProfileIn( $fname );
1595
1596 if ( '' == $query ) {
1597 $q = 'action=edit';
1598 } else {
1599 $q = 'action=edit&'.$query;
1600 }
1601 $u = $nt->escapeLocalURL( $q );
1602
1603 if ( '' == $text ) {
1604 $text = htmlspecialchars( $nt->getPrefixedText() );
1605 }
1606 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1607
1608 $inside = '';
1609 if ( '' != $trail ) {
1610 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1611 $inside = $m[1];
1612 $trail = $m[2];
1613 }
1614 }
1615 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1616 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1617 } else {
1618 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1619 }
1620
1621 wfProfileOut( $fname );
1622 return $s;
1623 }
1624
1625 # Pass a title object, not a title string
1626 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1627 {
1628 global $wgOut, $wgUser;
1629
1630 $link = $nt->getPrefixedURL();
1631
1632 $u = $nt->escapeLocalURL( $query );
1633
1634 if ( '' == $text ) {
1635 $text = htmlspecialchars( $nt->getPrefixedText() );
1636 }
1637 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1638
1639 $inside = '';
1640 if ( '' != $trail ) {
1641 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1642 $inside = $m[1];
1643 $trail = $m[2];
1644 }
1645 }
1646 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1647 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1648 } else {
1649 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1650 }
1651 return $s;
1652 }
1653
1654 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1655 {
1656 $u = $nt->escapeLocalURL( $query );
1657 if ( '' == $text ) {
1658 $text = htmlspecialchars( $nt->getPrefixedText() );
1659 }
1660 $inside = '';
1661 if ( '' != $trail ) {
1662 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1663 $inside = $m[1];
1664 $trail = $m[2];
1665 }
1666 }
1667 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1668 }
1669
1670 /* these are used extensively in SkinPHPTal, but also some other places */
1671 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1672 $title = Title::makeTitle( NS_SPECIAL, $name );
1673 $this->checkTitle($title, $name);
1674 return $title->getLocalURL( $urlaction );
1675 }
1676 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1677 $title = Title::newFromText( $name );
1678 $title = $title->getTalkPage();
1679 $this->checkTitle($title, $name);
1680 return $title->getLocalURL( $urlaction );
1681 }
1682 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1683 $title = Title::newFromText( $name );
1684 $title= $title->getSubjectPage();
1685 $this->checkTitle($title, $name);
1686 return $title->getLocalURL( $urlaction );
1687 }
1688 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1689 $title = Title::newFromText( wfMsg($name) );
1690 $this->checkTitle($title, $name);
1691 return $title->getLocalURL( $urlaction );
1692 }
1693 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1694 $title = Title::newFromText( $name );
1695 $this->checkTitle($title, $name);
1696 return $title->getLocalURL( $urlaction );
1697 }
1698 # this can be passed the NS number as defined in Language.php
1699 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1700 $title = Title::makeTitle( $namespace, $name );
1701 $this->checkTitle($title, $name);
1702 return $title->getLocalURL( $urlaction );
1703 }
1704
1705 /* these return an array with the 'href' and boolean 'exists' */
1706 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1707 $title = Title::newFromText( $name );
1708 $this->checkTitle($title, $name);
1709 return array(
1710 'href' => $title->getLocalURL( $urlaction ),
1711 'exists' => $title->getArticleID() != 0?true:false
1712 );
1713 }
1714 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1715 $title = Title::newFromText( $name );
1716 $title = $title->getTalkPage();
1717 $this->checkTitle($title, $name);
1718 return array(
1719 'href' => $title->getLocalURL( $urlaction ),
1720 'exists' => $title->getArticleID() != 0?true:false
1721 );
1722 }
1723 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1724 $title = Title::newFromText( $name );
1725 $title= $title->getSubjectPage();
1726 $this->checkTitle($title, $name);
1727 return array(
1728 'href' => $title->getLocalURL( $urlaction ),
1729 'exists' => $title->getArticleID() != 0?true:false
1730 );
1731 }
1732 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1733 $title = Title::newFromText( wfMsg($name) );
1734 $this->checkTitle($title, $name);
1735 return array(
1736 'href' => $title->getLocalURL( $urlaction ),
1737 'exists' => $title->getArticleID() != 0?true:false
1738 );
1739 }
1740
1741 # make sure we have some title to operate on
1742 /*static*/ function checkTitle ( &$title, &$name ) {
1743 if(!is_object($title)) {
1744 $title = Title::newFromText( $name );
1745 if(!is_object($title)) {
1746 $title = Title::newFromText( '--error: link target missing--' );
1747 }
1748 }
1749 }
1750
1751 function fnamePart( $url )
1752 {
1753 $basename = strrchr( $url, '/' );
1754 if ( false === $basename ) {
1755 $basename = $url;
1756 } else {
1757 $basename = substr( $basename, 1 );
1758 }
1759 return htmlspecialchars( $basename );
1760 }
1761
1762 function makeImage( $url, $alt = '' )
1763 {
1764 global $wgOut;
1765
1766 if ( '' == $alt ) {
1767 $alt = $this->fnamePart( $url );
1768 }
1769 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1770 return $s;
1771 }
1772
1773 function makeImageLink( $name, $url, $alt = '' ) {
1774 $nt = Title::makeTitle( Namespace::getImage(), $name );
1775 return $this->makeImageLinkObj( $nt, $alt );
1776 }
1777
1778 function makeImageLinkObj( $nt, $alt = '' ) {
1779 global $wgLang, $wgUseImageResize;
1780 $img = Image::newFromTitle( $nt );
1781 $url = $img->getURL();
1782
1783 $align = '';
1784 $prefix = $postfix = '';
1785
1786 if ( $wgUseImageResize ) {
1787 # Check if the alt text is of the form "options|alt text"
1788 # Options are:
1789 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1790 # * left no resizing, just left align. label is used for alt= only
1791 # * right same, but right aligned
1792 # * none same, but not aligned
1793 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1794 # * center center the image
1795 # * framed Keep original image size, no magnify-button.
1796
1797 $part = explode( '|', $alt);
1798
1799 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1800 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1801 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1802 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1803 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1804 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1805 $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
1806 $alt = $part[count($part)-1];
1807
1808 $height = $framed = $thumb = false;
1809 $manual_thumb = "" ;
1810
1811 foreach( $part as $key => $val ) {
1812 $val_parts = explode ( "=" , $val , 2 ) ;
1813 $left_part = array_shift ( $val_parts ) ;
1814 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1815 $thumb=true;
1816 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1817 # use manually specified thumbnail
1818 $thumb=true;
1819 $manual_thumb = array_shift ( $val_parts ) ;
1820 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1821 # remember to set an alignment, don't render immediately
1822 $align = 'right';
1823 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1824 # remember to set an alignment, don't render immediately
1825 $align = 'left';
1826 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1827 # remember to set an alignment, don't render immediately
1828 $align = 'center';
1829 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1830 # remember to set an alignment, don't render immediately
1831 $align = 'none';
1832 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1833 # $match is the image width in pixels
1834 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1835 $width = intval( $m[1] );
1836 $height = intval( $m[2] );
1837 } else {
1838 $width = intval($match);
1839 }
1840 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1841 $framed=true;
1842 }
1843 }
1844 if ( 'center' == $align )
1845 {
1846 $prefix = '<span style="text-align: center">';
1847 $postfix = '</span>';
1848 $align = 'none';
1849 }
1850
1851 if ( $thumb || $framed ) {
1852
1853 # Create a thumbnail. Alignment depends on language
1854 # writing direction, # right aligned for left-to-right-
1855 # languages ("Western languages"), left-aligned
1856 # for right-to-left-languages ("Semitic languages")
1857 #
1858 # If thumbnail width has not been provided, it is set
1859 # here to 180 pixels
1860 if ( $align == '' ) {
1861 $align = $wgLang->isRTL() ? 'left' : 'right';
1862 }
1863 if ( ! isset($width) ) {
1864 $width = 180;
1865 }
1866 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1867
1868 } elseif ( isset($width) ) {
1869
1870 # Create a resized image, without the additional thumbnail
1871 # features
1872
1873 if ( ( ! $height === false )
1874 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1875 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1876 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1877 $width = $img->getWidth() * $height / $img->getHeight();
1878 }
1879 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1880 }
1881 } # endif $wgUseImageResize
1882
1883 if ( empty( $alt ) ) {
1884 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1885 }
1886 $alt = htmlspecialchars( $alt );
1887
1888 $u = $nt->escapeLocalURL();
1889 if ( $url == '' )
1890 {
1891 $s = wfMsg( 'missingimage', $img->getName() );
1892 $s .= "<br>{$alt}<br>{$url}<br>\n";
1893 } else {
1894 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1895 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1896 }
1897 if ( '' != $align ) {
1898 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1899 }
1900 return str_replace("\n", ' ',$prefix.$s.$postfix);
1901 }
1902
1903 # Make HTML for a thumbnail including image, border and caption
1904 # $img is an Image object
1905 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1906 global $wgStylePath, $wgLang;
1907 # $image = Title::makeTitle( Namespace::getImage(), $name );
1908 $url = $img->getURL();
1909
1910 #$label = htmlspecialchars( $label );
1911 $alt = preg_replace( '/<[^>]*>/', '', $label);
1912 $alt = htmlspecialchars( $alt );
1913
1914 $width = $height = 0;
1915 if ( $img->exists() )
1916 {
1917 $width = $img->getWidth();
1918 $height = $img->getHeight();
1919 }
1920 if ( 0 == $width || 0 == $height )
1921 {
1922 $width = $height = 200;
1923 }
1924 if ( $boxwidth == 0 )
1925 {
1926 $boxwidth = 200;
1927 }
1928 if ( $framed )
1929 {
1930 // Use image dimensions, don't scale
1931 $boxwidth = $width;
1932 $oboxwidth = $boxwidth + 2;
1933 $boxheight = $height;
1934 $thumbUrl = $url;
1935 } else {
1936 $h = intval( $height/($width/$boxwidth) );
1937 $oboxwidth = $boxwidth + 2;
1938 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1939 {
1940 $boxwidth *= $boxheight/$h;
1941 } else {
1942 $boxheight = $h;
1943 }
1944 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1945 }
1946
1947 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1948 {
1949 $manual_title = Title::makeTitle( Namespace::getImage(), $manual_thumb ); #new Title ( $manual_thumb ) ;
1950 $manual_img = Image::newFromTitle( $manual_title );
1951 $thumbUrl = $manual_img->getURL();
1952 if ( $manual_img->exists() )
1953 {
1954 $width = $manual_img->getWidth();
1955 $height = $manual_img->getHeight();
1956 $boxwidth = $width ;
1957 $boxheight = $height ;
1958 $oboxwidth = $boxwidth + 2 ;
1959 }
1960 }
1961
1962 $u = $img->getEscapeLocalURL();
1963
1964 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1965 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1966 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1967
1968 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1969 if ( $thumbUrl == '' ) {
1970 $s .= wfMsg( 'missingimage', $img->getName() );
1971 $zoomicon = '';
1972 } else {
1973 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1974 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1975 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1976 if ( $framed ) {
1977 $zoomicon="";
1978 } else {
1979 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1980 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1981 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1982 'width="15" height="11" alt="'.$more.'" /></a></div>';
1983 }
1984 }
1985 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1986 return str_replace("\n", ' ', $s);
1987 }
1988
1989 function makeMediaLink( $name, $url, $alt = "" ) {
1990 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1991 return $this->makeMediaLinkObj( $nt, $alt );
1992 }
1993
1994 function makeMediaLinkObj( $nt, $alt = "" )
1995 {
1996 if ( ! isset( $nt ) )
1997 {
1998 ### HOTFIX. Instead of breaking, return empty string.
1999 $s = $alt;
2000 } else {
2001 $name = $nt->getDBKey();
2002 $url = Image::wfImageUrl( $name );
2003 if ( empty( $alt ) ) {
2004 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2005 }
2006
2007 $u = htmlspecialchars( $url );
2008 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2009 }
2010 return $s;
2011 }
2012
2013 function specialLink( $name, $key = "" )
2014 {
2015 global $wgLang;
2016
2017 if ( '' == $key ) { $key = strtolower( $name ); }
2018 $pn = $wgLang->ucfirst( $name );
2019 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2020 wfMsg( $key ) );
2021 }
2022
2023 function makeExternalLink( $url, $text, $escape = true ) {
2024 $style = $this->getExternalLinkAttributes( $url, $text );
2025 $url = htmlspecialchars( $url );
2026 if( $escape ) {
2027 $text = htmlspecialchars( $text );
2028 }
2029 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2030 }
2031
2032 # Called by history lists and recent changes
2033 #
2034
2035 # Returns text for the start of the tabular part of RC
2036 function beginRecentChangesList()
2037 {
2038 $this->rc_cache = array() ;
2039 $this->rcMoveIndex = 0;
2040 $this->rcCacheIndex = 0 ;
2041 $this->lastdate = '';
2042 $this->rclistOpen = false;
2043 return '';
2044 }
2045
2046 function beginImageHistoryList()
2047 {
2048 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2049 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2050 return $s;
2051 }
2052
2053 # Returns text for the end of RC
2054 # If enhanced RC is in use, returns pretty much all the text
2055 function endRecentChangesList()
2056 {
2057 $s = $this->recentChangesBlock() ;
2058 if( $this->rclistOpen ) {
2059 $s .= "</ul>\n";
2060 }
2061 return $s;
2062 }
2063
2064 # Enhanced RC ungrouped line
2065 function recentChangesBlockLine ( $rcObj )
2066 {
2067 global $wgStylePath, $wgLang ;
2068
2069 # Get rc_xxxx variables
2070 extract( $rcObj->mAttribs ) ;
2071 $curIdEq = 'curid='.$rc_cur_id;
2072
2073 # Spacer image
2074 $r = '' ;
2075
2076 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2077 $r .= '<tt>' ;
2078
2079 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2080 $r .= '&nbsp;&nbsp;';
2081 } else {
2082 # M & N (minor & new)
2083 $M = wfMsg( 'minoreditletter' );
2084 $N = wfMsg( 'newpageletter' );
2085
2086 if ( $rc_type == RC_NEW ) {
2087 $r .= $N ;
2088 } else {
2089 $r .= '&nbsp;' ;
2090 }
2091 if ( $rc_minor ) {
2092 $r .= $M ;
2093 } else {
2094 $r .= '&nbsp;' ;
2095 }
2096 }
2097
2098 # Timestamp
2099 $r .= ' '.$rcObj->timestamp.' ' ;
2100 $r .= '</tt>' ;
2101
2102 # Article link
2103 $link = $rcObj->link ;
2104 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2105 $r .= $link ;
2106
2107 # Diff
2108 $r .= ' (' ;
2109 $r .= $rcObj->difflink ;
2110 $r .= '; ' ;
2111
2112 # Hist
2113 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2114
2115 # User/talk
2116 $r .= ') . . '.$rcObj->userlink ;
2117 $r .= $rcObj->usertalklink ;
2118
2119 # Comment
2120 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2121 $rc_comment=$this->formatComment($rc_comment);
2122 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2123 }
2124
2125 $r .= "<br />\n" ;
2126 return $r ;
2127 }
2128
2129 # Enhanced RC group
2130 function recentChangesBlockGroup ( $block )
2131 {
2132 global $wgStylePath, $wgLang ;
2133
2134 $r = '' ;
2135 $M = wfMsg( 'minoreditletter' );
2136 $N = wfMsg( 'newpageletter' );
2137
2138 # Collate list of users
2139 $isnew = false ;
2140 $userlinks = array () ;
2141 foreach ( $block AS $rcObj ) {
2142 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2143 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2144 $u = $rcObj->userlink ;
2145 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2146 $userlinks[$u]++ ;
2147 }
2148
2149 # Sort the list and convert to text
2150 krsort ( $userlinks ) ;
2151 asort ( $userlinks ) ;
2152 $users = array () ;
2153 foreach ( $userlinks as $userlink => $count) {
2154 $text = $userlink ;
2155 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2156 array_push ( $users , $text ) ;
2157 }
2158 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2159
2160 # Arrow
2161 $rci = 'RCI'.$this->rcCacheIndex ;
2162 $rcl = 'RCL'.$this->rcCacheIndex ;
2163 $rcm = 'RCM'.$this->rcCacheIndex ;
2164 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2165 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2166 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2167 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2168 $r .= $tl ;
2169
2170 # Main line
2171 # M/N
2172 $r .= '<tt>' ;
2173 if ( $isnew ) $r .= $N ;
2174 else $r .= '&nbsp;' ;
2175 $r .= '&nbsp;' ; # Minor
2176
2177 # Timestamp
2178 $r .= ' '.$block[0]->timestamp.' ' ;
2179 $r .= '</tt>' ;
2180
2181 # Article link
2182 $link = $block[0]->link ;
2183 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2184 $r .= $link ;
2185
2186 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2187 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2188 # Changes
2189 $r .= ' ('.count($block).' ' ;
2190 if ( $isnew ) $r .= wfMsg('changes');
2191 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2192 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2193 $r .= '; ' ;
2194
2195 # History
2196 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2197 $r .= ')' ;
2198 }
2199
2200 $r .= $users ;
2201 $r .= "<br />\n" ;
2202
2203 # Sub-entries
2204 $r .= '<div id="'.$rci.'" style="display:none">' ;
2205 foreach ( $block AS $rcObj ) {
2206 # Get rc_xxxx variables
2207 extract( $rcObj->mAttribs );
2208
2209 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2210 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2211 if ( $rc_new ) $r .= $N ;
2212 else $r .= '&nbsp;' ;
2213 if ( $rc_minor ) $r .= $M ;
2214 else $r .= '&nbsp;' ;
2215 $r .= '</tt>' ;
2216
2217 $o = '' ;
2218 if ( $rc_last_oldid != 0 ) {
2219 $o = 'oldid='.$rc_last_oldid ;
2220 }
2221 if ( $rc_type == RC_LOG ) {
2222 $link = $rcObj->timestamp ;
2223 } else {
2224 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2225 }
2226 $link = '<tt>'.$link.'</tt>' ;
2227
2228 $r .= $link ;
2229 $r .= ' (' ;
2230 $r .= $rcObj->curlink ;
2231 $r .= '; ' ;
2232 $r .= $rcObj->lastlink ;
2233 $r .= ') . . '.$rcObj->userlink ;
2234 $r .= $rcObj->usertalklink ;
2235 if ( $rc_comment != '' ) {
2236 $rc_comment=$this->formatComment($rc_comment);
2237 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2238 }
2239 $r .= "<br />\n" ;
2240 }
2241 $r .= "</div>\n" ;
2242
2243 $this->rcCacheIndex++ ;
2244 return $r ;
2245 }
2246
2247 # If enhanced RC is in use, this function takes the previously cached
2248 # RC lines, arranges them, and outputs the HTML
2249 function recentChangesBlock ()
2250 {
2251 global $wgStylePath ;
2252 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2253 $blockOut = '';
2254 foreach ( $this->rc_cache AS $secureName => $block ) {
2255 if ( count ( $block ) < 2 ) {
2256 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2257 } else {
2258 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2259 }
2260 }
2261
2262 return '<div>'.$blockOut.'</div>' ;
2263 }
2264
2265 # Called in a loop over all displayed RC entries
2266 # Either returns the line, or caches it for later use
2267 function recentChangesLine( &$rc, $watched = false )
2268 {
2269 global $wgUser ;
2270 $usenew = $wgUser->getOption( 'usenewrc' );
2271 if ( $usenew )
2272 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2273 else
2274 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2275 return $line ;
2276 }
2277
2278 function recentChangesLineOld( &$rc, $watched = false )
2279 {
2280 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2281
2282 # Extract DB fields into local scope
2283 extract( $rc->mAttribs );
2284 $curIdEq = 'curid=' . $rc_cur_id;
2285
2286 # Make date header if necessary
2287 $date = $wgLang->date( $rc_timestamp, true);
2288 $s = '';
2289 if ( $date != $this->lastdate ) {
2290 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2291 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2292 $this->lastdate = $date;
2293 $this->rclistOpen = true;
2294 }
2295
2296 # If this edit has not yet been patrolled, make it stick out
2297 $s .= ( ! $wgUseRCPatrol || $rc_patrolled ) ? '<li> ' : '<li class="not_patrolled"> ';
2298
2299 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2300 # Diff
2301 $s .= '(' . wfMsg( 'diff' ) . ') (';
2302 # Hist
2303 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2304 ') . . ';
2305
2306 # "[[x]] moved to [[y]]"
2307 $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
2308 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2309 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2310 } else {
2311 # Diff link
2312 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2313 $diffLink = wfMsg( 'diff' );
2314 } else {
2315 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2316 ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2317 $rcidparam = "&rcid={$rc_id}";
2318 else
2319 $rcidparam = "";
2320 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2321 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2322 '', '', ' tabindex="'.$rc->counter.'"');
2323 }
2324 $s .= '('.$diffLink.') (';
2325
2326 # History link
2327 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2328 $s .= ') . . ';
2329
2330 # M and N (minor and new)
2331 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2332 if ( $rc_type == RC_NEW ) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2333
2334 # Article link
2335 # If it's a new article, there is no diff link, but if it hasn't been
2336 # patrolled yet, we need to give users a way to do so
2337 if ( $wgUseRCPatrol && $rc_type == RC_NEW && $rc_patrolled == 0 &&
2338 $wgUser->getID() != 0 && ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2339 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2340 else
2341 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2342
2343 if ( $watched ) {
2344 $articleLink = '<strong>'.$articleLink.'</strong>';
2345 }
2346 $s .= ' '.$articleLink;
2347
2348 }
2349
2350 # Timestamp
2351 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2352
2353 # User link (or contributions for unregistered users)
2354 if ( 0 == $rc_user ) {
2355 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2356 $rc_user_text, 'target=' . $rc_user_text );
2357 } else {
2358 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2359 }
2360 $s .= $userLink;
2361
2362 # User talk link
2363 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2364 global $wgDisableAnonTalk;
2365 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2366 $userTalkLink = '';
2367 } else {
2368 $utns=$wgLang->getNsText(NS_USER_TALK);
2369 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2370 }
2371 # Block link
2372 $blockLink='';
2373 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2374 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2375 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2376
2377 }
2378 if($blockLink) {
2379 if($userTalkLink) $userTalkLink .= ' | ';
2380 $userTalkLink .= $blockLink;
2381 }
2382 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2383
2384 # Add comment
2385 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2386 $rc_comment=$this->formatComment($rc_comment);
2387 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2388 }
2389 $s .= "</li>\n";
2390
2391 return $s;
2392 }
2393
2394 function recentChangesLineNew( &$baseRC, $watched = false )
2395 {
2396 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2397
2398 # Create a specialised object
2399 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2400
2401 # Extract fields from DB into the function scope (rc_xxxx variables)
2402 extract( $rc->mAttribs );
2403 $curIdEq = 'curid=' . $rc_cur_id;
2404
2405 # If it's a new day, add the headline and flush the cache
2406 $date = $wgLang->date( $rc_timestamp, true);
2407 $ret = '';
2408 if ( $date != $this->lastdate ) {
2409 # Process current cache
2410 $ret = $this->recentChangesBlock () ;
2411 $this->rc_cache = array() ;
2412 $ret .= "<h4>{$date}</h4>\n";
2413 $this->lastdate = $date;
2414 }
2415
2416 # Make article link
2417 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2418 $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
2419 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2420 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2421 } else {
2422 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2423 }
2424
2425 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2426 $rc->watched = $watched ;
2427 $rc->link = $clink ;
2428 $rc->timestamp = $time;
2429
2430 # Make "cur" and "diff" links
2431 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2432 $curLink = wfMsg( 'cur' );
2433 $diffLink = wfMsg( 'diff' );
2434 } else {
2435 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2436 $aprops = ' tabindex="'.$baseRC->counter.'"';
2437 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2438 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2439 }
2440
2441 # Make "last" link
2442 $titleObj = $rc->getTitle();
2443 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2444 $lastLink = wfMsg( 'last' );
2445 } else {
2446 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2447 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2448 }
2449
2450 # Make user link (or user contributions for unregistered users)
2451 if ( $rc_user == 0 ) {
2452 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2453 $rc_user_text, 'target=' . $rc_user_text );
2454 } else {
2455 $userLink = $this->makeLink( $wgLang->getNsText(
2456 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2457 }
2458
2459 $rc->userlink = $userLink;
2460 $rc->lastlink = $lastLink;
2461 $rc->curlink = $curLink;
2462 $rc->difflink = $diffLink;
2463
2464 # Make user talk link
2465 $utns=$wgLang->getNsText(NS_USER_TALK);
2466 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2467 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2468
2469 global $wgDisableAnonTalk;
2470 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2471 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2472 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2473 if( $wgDisableAnonTalk )
2474 $rc->usertalklink = ' ('.$blockLink.')';
2475 else
2476 $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
2477 } else {
2478 if( $wgDisableAnonTalk && ($rc_user == 0) )
2479 $rc->usertalklink = '';
2480 else
2481 $rc->usertalklink = ' ('.$userTalkLink.')';
2482 }
2483
2484 # Put accumulated information into the cache, for later display
2485 # Page moves go on their own line
2486 $title = $rc->getTitle();
2487 $secureName = $title->getPrefixedDBkey();
2488 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2489 # Use an @ character to prevent collision with page names
2490 $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
2491 } else {
2492 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2493 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2494 }
2495 return $ret;
2496 }
2497
2498 function endImageHistoryList()
2499 {
2500 $s = "</ul>\n";
2501 return $s;
2502 }
2503
2504 /* This function is called by all recent changes variants, by the page history,
2505 and by the user contributions list. It is responsible for formatting edit
2506 comments. It escapes any HTML in the comment, but adds some CSS to format
2507 auto-generated comments (from section editing) and formats [[wikilinks]].
2508 Main author: Erik Möller (moeller@scireview.de)
2509 */
2510 function formatComment($comment)
2511 {
2512 global $wgLang;
2513 $comment = htmlspecialchars( $comment );
2514
2515 # The pattern for autogen comments is / * foo * /, which makes for
2516 # some nasty regex.
2517 # We look for all comments, match any text before and after the comment,
2518 # add a separator where needed and format the comment itself with CSS
2519 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2520 $pre=$match[1];
2521 $auto=$match[2];
2522 $post=$match[3];
2523 $sep='-';
2524 if($pre) { $auto = $sep.' '.$auto; }
2525 if($post) { $auto .= ' '.$sep; }
2526 $auto='<span class="autocomment">'.$auto.'</span>';
2527 $comment=$pre.$auto.$post;
2528 }
2529
2530 # format regular and media links - all other wiki formatting
2531 # is ignored
2532 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2533 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2534 # Handle link renaming [[foo|text]] will show link as "text"
2535 if( "" != $match[3] ) {
2536 $text = $match[3];
2537 } else {
2538 $text = $match[1];
2539 }
2540 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2541 # Media link; trail not supported.
2542 $linkRegexp = '/\[\[(.*?)\]\]/';
2543 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2544 } else {
2545 # Other kind of link
2546 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2547 $trail = $submatch[1];
2548 } else {
2549 $trail = "";
2550 }
2551 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2552 if ($match[1][0] == ':')
2553 $match[1] = substr($match[1], 1);
2554 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2555 }
2556 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2557 }
2558 return $comment;
2559 }
2560
2561 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2562 {
2563 global $wgUser, $wgLang, $wgTitle;
2564
2565 $datetime = $wgLang->timeanddate( $timestamp, true );
2566 $del = wfMsg( 'deleteimg' );
2567 $delall = wfMsg( 'deleteimgcompletely' );
2568 $cur = wfMsg( 'cur' );
2569
2570 if ( $iscur ) {
2571 $url = Image::wfImageUrl( $img );
2572 $rlink = $cur;
2573 if ( $wgUser->isSysop() ) {
2574 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2575 '&action=delete' );
2576 $style = $this->getInternalLinkAttributes( $link, $delall );
2577
2578 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2579 } else {
2580 $dlink = $del;
2581 }
2582 } else {
2583 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2584 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2585 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2586 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2587 urlencode( $img ) );
2588 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2589 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2590 } else {
2591 # Having live active links for non-logged in users
2592 # means that bots and spiders crawling our site can
2593 # inadvertently change content. Baaaad idea.
2594 $rlink = wfMsg( 'revertimg' );
2595 $dlink = $del;
2596 }
2597 }
2598 if ( 0 == $user ) {
2599 $userlink = $usertext;
2600 } else {
2601 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2602 ':'.$usertext, $usertext );
2603 }
2604 $nbytes = wfMsg( 'nbytes', $size );
2605 $style = $this->getInternalLinkAttributes( $url, $datetime );
2606
2607 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2608 . " . . {$userlink} ({$nbytes})";
2609
2610 if ( '' != $description && '*' != $description ) {
2611 $sk=$wgUser->getSkin();
2612 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2613 }
2614 $s .= "</li>\n";
2615 return $s;
2616 }
2617
2618 function tocIndent($level) {
2619 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2620 }
2621
2622 function tocUnindent($level) {
2623 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2624 }
2625
2626 # parameter level defines if we are on an indentation level
2627 function tocLine( $anchor, $tocline, $level ) {
2628 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2629 if($level) {
2630 return $link."\n";
2631 } else {
2632 return '<div class="tocline">'.$link."</div>\n";
2633 }
2634
2635 }
2636
2637 function tocTable($toc) {
2638 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2639 # try min-width & co when somebody gets a chance
2640 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2641 return
2642 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2643 '<b>'.wfMsg('toc').'</b>' .
2644 $hideline .
2645 '</td></tr><tr id="tocinside"><td>'."\n".
2646 $toc."</td></tr></table>\n";
2647 }
2648
2649 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2650 function editSectionScript( $section, $head ) {
2651 global $wgTitle, $wgRequest;
2652 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2653 return $head;
2654 }
2655 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2656 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2657 }
2658
2659 function editSectionLink( $section ) {
2660 global $wgRequest;
2661 global $wgTitle, $wgUser, $wgLang;
2662
2663 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2664 # Section edit links would be out of sync on an old page.
2665 # But, if we're diffing to the current page, they'll be
2666 # correct.
2667 return '';
2668 }
2669
2670 $editurl = '&section='.$section;
2671 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2672
2673 if( $wgLang->isRTL() ) {
2674 $farside = 'left';
2675 $nearside = 'right';
2676 } else {
2677 $farside = 'right';
2678 $nearside = 'left';
2679 }
2680 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2681
2682 }
2683
2684 // This function is called by EditPage.php and shows a bulletin board style
2685 // toolbar for common editing functions. It can be disabled in the user preferences.
2686 // The necsesary JavaScript code can be found in style/wikibits.js.
2687 function getEditToolbar() {
2688 global $wgStylePath, $wgLang, $wgMimeType;
2689
2690 // toolarray an array of arrays which each include the filename of
2691 // the button image (without path), the opening tag, the closing tag,
2692 // and optionally a sample text that is inserted between the two when no
2693 // selection is highlighted.
2694 // The tip text is shown when the user moves the mouse over the button.
2695
2696 // Already here are accesskeys (key), which are not used yet until someone
2697 // can figure out a way to make them work in IE. However, we should make
2698 // sure these keys are not defined on the edit page.
2699 $toolarray=array(
2700 array( 'image'=>'button_bold.png',
2701 'open'=>"\'\'\'",
2702 'close'=>"\'\'\'",
2703 'sample'=>wfMsg('bold_sample'),
2704 'tip'=>wfMsg('bold_tip'),
2705 'key'=>'B'
2706 ),
2707 array( "image"=>"button_italic.png",
2708 "open"=>"\'\'",
2709 "close"=>"\'\'",
2710 "sample"=>wfMsg("italic_sample"),
2711 "tip"=>wfMsg("italic_tip"),
2712 "key"=>"I"
2713 ),
2714 array( "image"=>"button_link.png",
2715 "open"=>"[[",
2716 "close"=>"]]",
2717 "sample"=>wfMsg("link_sample"),
2718 "tip"=>wfMsg("link_tip"),
2719 "key"=>"L"
2720 ),
2721 array( "image"=>"button_extlink.png",
2722 "open"=>"[",
2723 "close"=>"]",
2724 "sample"=>wfMsg("extlink_sample"),
2725 "tip"=>wfMsg("extlink_tip"),
2726 "key"=>"X"
2727 ),
2728 array( "image"=>"button_headline.png",
2729 "open"=>"\\n== ",
2730 "close"=>" ==\\n",
2731 "sample"=>wfMsg("headline_sample"),
2732 "tip"=>wfMsg("headline_tip"),
2733 "key"=>"H"
2734 ),
2735 array( "image"=>"button_image.png",
2736 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2737 "close"=>"]]",
2738 "sample"=>wfMsg("image_sample"),
2739 "tip"=>wfMsg("image_tip"),
2740 "key"=>"D"
2741 ),
2742 array( "image"=>"button_media.png",
2743 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2744 "close"=>"]]",
2745 "sample"=>wfMsg("media_sample"),
2746 "tip"=>wfMsg("media_tip"),
2747 "key"=>"M"
2748 ),
2749 array( "image"=>"button_math.png",
2750 "open"=>"\\<math\\>",
2751 "close"=>"\\</math\\>",
2752 "sample"=>wfMsg("math_sample"),
2753 "tip"=>wfMsg("math_tip"),
2754 "key"=>"C"
2755 ),
2756 array( "image"=>"button_nowiki.png",
2757 "open"=>"\\<nowiki\\>",
2758 "close"=>"\\</nowiki\\>",
2759 "sample"=>wfMsg("nowiki_sample"),
2760 "tip"=>wfMsg("nowiki_tip"),
2761 "key"=>"N"
2762 ),
2763 array( "image"=>"button_sig.png",
2764 "open"=>"--~~~~",
2765 "close"=>"",
2766 "sample"=>"",
2767 "tip"=>wfMsg("sig_tip"),
2768 "key"=>"Y"
2769 ),
2770 array( "image"=>"button_hr.png",
2771 "open"=>"\\n----\\n",
2772 "close"=>"",
2773 "sample"=>"",
2774 "tip"=>wfMsg("hr_tip"),
2775 "key"=>"R"
2776 )
2777 );
2778 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2779
2780 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2781 foreach($toolarray as $tool) {
2782
2783 $image=$wgStylePath.'/images/'.$tool['image'];
2784 $open=$tool['open'];
2785 $close=$tool['close'];
2786 $sample = addslashes( $tool['sample'] );
2787
2788 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2789 // Older browsers show a "speedtip" type message only for ALT.
2790 // Ideally these should be different, realistically they
2791 // probably don't need to be.
2792 $tip = addslashes( $tool['tip'] );
2793
2794 #$key = $tool["key"];
2795
2796 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2797 }
2798
2799 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2800 $toolbar.="document.writeln(\"</div>\");\n";
2801
2802 $toolbar.="/*]]>*/\n</script>";
2803 return $toolbar;
2804 }
2805
2806 /* public */ function suppressUrlExpansion() {
2807 return false;
2808 }
2809 }
2810
2811 }
2812 ?>