Disable $wgUseGzip by default since it's wildly incompatible with
[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 $s = '<a href="' . $titleObj->escapeLocalURL()
885 . '"><img'.$a.' src="'
886 . $this->getLogo() . '" alt="' . "[{$mp}]\" /></a>";
887 return $s;
888 }
889
890 function quickBar()
891 {
892 global $wgOut, $wgTitle, $wgUser, $wgRequest, $wgLang;
893 global $wgDisableUploads, $wgRemoteUploads;
894
895 $fname = 'Skin::quickBar';
896 wfProfileIn( $fname );
897
898 $action = $wgRequest->getText( 'action' );
899 $wpPreview = $wgRequest->getBool( 'wpPreview' );
900 $tns=$wgTitle->getNamespace();
901
902 $s = "\n<div id='quickbar'>";
903 $s .= "\n" . $this->logoText() . "\n<hr class='sep' />";
904
905 $sep = "\n<br />";
906 $s .= $this->mainPageLink()
907 . $sep . $this->specialLink( 'recentchanges' )
908 . $sep . $this->specialLink( 'randompage' );
909 if ($wgUser->getID()) {
910 $s.= $sep . $this->specialLink( 'watchlist' ) ;
911 $s .= $sep .$this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
912 wfMsg( 'mycontris' ), 'target=' . wfUrlencode($wgUser->getName() ) );
913
914 }
915 // only show watchlist link if logged in
916 if ( wfMsg ( 'currentevents' ) != '-' ) $s .= $sep . $this->makeKnownLink( wfMsg( 'currentevents' ), '' ) ;
917 $s .= "\n<br /><hr class='sep' />";
918 $articleExists = $wgTitle->getArticleId();
919 if ( $wgOut->isArticle() || $action =='edit' || $action =='history' || $wpPreview) {
920 if($wgOut->isArticle()) {
921 $s .= '<strong>' . $this->editThisPage() . '</strong>';
922 } else { # backlink to the article in edit or history mode
923 if($articleExists){ # no backlink if no article
924 switch($tns) {
925 case 0:
926 $text = wfMsg('articlepage');
927 break;
928 case 1:
929 $text = wfMsg('viewtalkpage');
930 break;
931 case 2:
932 $text = wfMsg('userpage');
933 break;
934 case 3:
935 $text = wfMsg('viewtalkpage');
936 break;
937 case 4:
938 $text = wfMsg('wikipediapage');
939 break;
940 case 5:
941 $text = wfMsg('viewtalkpage');
942 break;
943 case 6:
944 $text = wfMsg('imagepage');
945 break;
946 case 7:
947 $text = wfMsg('viewtalkpage');
948 break;
949 default:
950 $text= wfMsg('articlepage');
951 }
952
953 $link = $wgTitle->getText();
954 if ($nstext = $wgLang->getNsText($tns) ) { # add namespace if necessary
955 $link = $nstext . ':' . $link ;
956 }
957
958 $s .= $this->makeLink( $link, $text );
959 } elseif( $wgTitle->getNamespace() != Namespace::getSpecial() ) {
960 # we just throw in a "New page" text to tell the user that he's in edit mode,
961 # and to avoid messing with the separator that is prepended to the next item
962 $s .= '<strong>' . wfMsg('newpage') . '</strong>';
963 }
964
965 }
966
967
968 if( $tns%2 && $action!='edit' && !$wpPreview) {
969 $s.= '<br />'.$this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('postcomment'),'action=edit&section=new');
970 }
971
972 /*
973 watching could cause problems in edit mode:
974 if user edits article, then loads "watch this article" in background and then saves
975 article with "Watch this article" checkbox disabled, the article is transparently
976 unwatched. Therefore we do not show the "Watch this page" link in edit mode
977 */
978 if ( 0 != $wgUser->getID() && $articleExists) {
979 if($action!='edit' && $action != 'submit' )
980 {
981 $s .= $sep . $this->watchThisPage();
982 }
983 if ( $wgTitle->userCanEdit() )
984 $s .= $sep . $this->moveThisPage();
985 }
986 if ( $wgUser->isSysop() and $articleExists ) {
987 $s .= $sep . $this->deleteThisPage() .
988 $sep . $this->protectThisPage();
989 }
990 $s .= $sep . $this->talkLink();
991 if ($articleExists && $action !='history') {
992 $s .= $sep . $this->historyLink();
993 }
994 $s.=$sep . $this->whatLinksHere();
995
996 if($wgOut->isArticleRelated()) {
997 $s .= $sep . $this->watchPageLinksLink();
998 }
999
1000 if ( Namespace::getUser() == $wgTitle->getNamespace()
1001 || $wgTitle->getNamespace() == Namespace::getTalk(Namespace::getUser())
1002 ) {
1003
1004 $id=User::idFromName($wgTitle->getText());
1005 $ip=User::isIP($wgTitle->getText());
1006
1007 if($id||$ip) {
1008 $s .= $sep . $this->userContribsLink();
1009 }
1010 if ( 0 != $wgUser->getID() ) {
1011 if($id) { # can only email real users
1012 $s .= $sep . $this->emailUserLink();
1013 }
1014 }
1015 }
1016 $s .= "\n<br /><hr class='sep' />";
1017 }
1018
1019 if ( 0 != $wgUser->getID() && ( !$wgDisableUploads || $wgRemoteUploads ) ) {
1020 $s .= $this->specialLink( 'upload' ) . $sep;
1021 }
1022 $s .= $this->specialLink( 'specialpages' )
1023 . $sep . $this->bugReportsLink();
1024
1025 global $wgSiteSupportPage;
1026 if( $wgSiteSupportPage ) {
1027 $s .= "\n<br /><a href=\"" . htmlspecialchars( $wgSiteSupportPage ) .
1028 '" class="internal">' . wfMsg( 'sitesupport' ) . '</a>';
1029 }
1030
1031 $s .= "\n<br /></div>\n";
1032 wfProfileOut( $fname );
1033 return $s;
1034 }
1035
1036 function specialPagesList()
1037 {
1038 global $wgUser, $wgOut, $wgLang, $wgServer, $wgRedirectScript;
1039 require_once('SpecialPage.php');
1040 $a = array();
1041 $pages = SpecialPage::getPages();
1042
1043 foreach ( $pages[''] as $name => $page ) {
1044 $a[$name] = $page->getDescription();
1045 }
1046 if ( $wgUser->isSysop() )
1047 {
1048 foreach ( $pages['sysop'] as $name => $page ) {
1049 $a[$name] = $page->getDescription();
1050 }
1051 }
1052 if ( $wgUser->isDeveloper() )
1053 {
1054 foreach ( $pages['developer'] as $name => $page ) {
1055 $a[$name] = $page->getDescription() ;
1056 }
1057 }
1058 $go = wfMsg( 'go' );
1059 $sp = wfMsg( 'specialpages' );
1060 $spp = $wgLang->specialPage( 'Specialpages' );
1061
1062 $s = '<form id="specialpages" method="get" class="inline" ' .
1063 'action="' . htmlspecialchars( "{$wgServer}{$wgRedirectScript}" ) . "\">\n";
1064 $s .= "<select name=\"wpDropdown\">\n";
1065 $s .= "<option value=\"{$spp}\">{$sp}</option>\n";
1066
1067 foreach ( $a as $name => $desc ) {
1068 $p = $wgLang->specialPage( $name );
1069 $s .= "<option value=\"{$p}\">{$desc}</option>\n";
1070 }
1071 $s .= "</select>\n";
1072 $s .= "<input type='submit' value=\"{$go}\" name='redirect' />\n";
1073 $s .= "</form>\n";
1074 return $s;
1075 }
1076
1077 function mainPageLink()
1078 {
1079 $mp = wfMsg( 'mainpage' );
1080 $s = $this->makeKnownLink( $mp, $mp );
1081 return $s;
1082 }
1083
1084 function copyrightLink()
1085 {
1086 $s = $this->makeKnownLink( wfMsg( 'copyrightpage' ),
1087 wfMsg( 'copyrightpagename' ) );
1088 return $s;
1089 }
1090
1091 function aboutLink()
1092 {
1093 $s = $this->makeKnownLink( wfMsg( 'aboutpage' ),
1094 wfMsg( 'aboutwikipedia' ) );
1095 return $s;
1096 }
1097
1098
1099 function disclaimerLink()
1100 {
1101 $s = $this->makeKnownLink( wfMsg( 'disclaimerpage' ),
1102 wfMsg( 'disclaimers' ) );
1103 return $s;
1104 }
1105
1106 function editThisPage()
1107 {
1108 global $wgOut, $wgTitle, $wgRequest;
1109
1110 $oldid = $wgRequest->getVal( 'oldid' );
1111 $diff = $wgRequest->getVal( 'diff' );
1112 $redirect = $wgRequest->getVal( 'redirect' );
1113
1114 if ( ! $wgOut->isArticleRelated() ) {
1115 $s = wfMsg( 'protectedpage' );
1116 } else {
1117 $n = $wgTitle->getPrefixedText();
1118 if ( $wgTitle->userCanEdit() ) {
1119 $t = wfMsg( 'editthispage' );
1120 } else {
1121 #$t = wfMsg( "protectedpage" );
1122 $t = wfMsg( 'viewsource' );
1123 }
1124 $oid = $red = '';
1125
1126 if ( !is_null( $redirect ) ) { $red = "&redirect={$redirect}"; }
1127 if ( $oldid && ! isset( $diff ) ) {
1128 $oid = "&oldid={$oldid}";
1129 }
1130 $s = $this->makeKnownLink( $n, $t, "action=edit{$oid}{$red}" );
1131 }
1132 return $s;
1133 }
1134
1135 function deleteThisPage()
1136 {
1137 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1138
1139 $diff = $wgRequest->getVal( 'diff' );
1140 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1141 $n = $wgTitle->getPrefixedText();
1142 $t = wfMsg( 'deletethispage' );
1143
1144 $s = $this->makeKnownLink( $n, $t, 'action=delete' );
1145 } else {
1146 $s = '';
1147 }
1148 return $s;
1149 }
1150
1151 function protectThisPage()
1152 {
1153 global $wgUser, $wgOut, $wgTitle, $wgRequest;
1154
1155 $diff = $wgRequest->getVal( 'diff' );
1156 if ( $wgTitle->getArticleId() && ( ! $diff ) && $wgUser->isSysop() ) {
1157 $n = $wgTitle->getPrefixedText();
1158
1159 if ( $wgTitle->isProtected() ) {
1160 $t = wfMsg( 'unprotectthispage' );
1161 $q = 'action=unprotect';
1162 } else {
1163 $t = wfMsg( 'protectthispage' );
1164 $q = 'action=protect';
1165 }
1166 $s = $this->makeKnownLink( $n, $t, $q );
1167 } else {
1168 $s = '';
1169 }
1170 return $s;
1171 }
1172
1173 function watchThisPage()
1174 {
1175 global $wgUser, $wgOut, $wgTitle;
1176
1177 if ( $wgOut->isArticleRelated() ) {
1178 $n = $wgTitle->getPrefixedText();
1179
1180 if ( $wgTitle->userIsWatching() ) {
1181 $t = wfMsg( 'unwatchthispage' );
1182 $q = 'action=unwatch';
1183 } else {
1184 $t = wfMsg( 'watchthispage' );
1185 $q = 'action=watch';
1186 }
1187 $s = $this->makeKnownLink( $n, $t, $q );
1188 } else {
1189 $s = wfMsg( 'notanarticle' );
1190 }
1191 return $s;
1192 }
1193
1194 function moveThisPage()
1195 {
1196 global $wgTitle, $wgLang;
1197
1198 if ( $wgTitle->userCanEdit() ) {
1199 $s = $this->makeKnownLink( $wgLang->specialPage( 'Movepage' ),
1200 wfMsg( 'movethispage' ), 'target=' . $wgTitle->getPrefixedURL() );
1201 } // no message if page is protected - would be redundant
1202 return $s;
1203 }
1204
1205 function historyLink()
1206 {
1207 global $wgTitle;
1208
1209 $s = $this->makeKnownLink( $wgTitle->getPrefixedText(),
1210 wfMsg( 'history' ), 'action=history' );
1211 return $s;
1212 }
1213
1214 function whatLinksHere()
1215 {
1216 global $wgTitle, $wgLang;
1217
1218 $s = $this->makeKnownLink( $wgLang->specialPage( 'Whatlinkshere' ),
1219 wfMsg( 'whatlinkshere' ), 'target=' . $wgTitle->getPrefixedURL() );
1220 return $s;
1221 }
1222
1223 function userContribsLink()
1224 {
1225 global $wgTitle, $wgLang;
1226
1227 $s = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
1228 wfMsg( 'contributions' ), 'target=' . $wgTitle->getPartialURL() );
1229 return $s;
1230 }
1231
1232 function emailUserLink()
1233 {
1234 global $wgTitle, $wgLang;
1235
1236 $s = $this->makeKnownLink( $wgLang->specialPage( 'Emailuser' ),
1237 wfMsg( 'emailuser' ), 'target=' . $wgTitle->getPartialURL() );
1238 return $s;
1239 }
1240
1241 function watchPageLinksLink()
1242 {
1243 global $wgOut, $wgTitle, $wgLang;
1244
1245 if ( ! $wgOut->isArticleRelated() ) {
1246 $s = '(' . wfMsg( 'notanarticle' ) . ')';
1247 } else {
1248 $s = $this->makeKnownLink( $wgLang->specialPage(
1249 'Recentchangeslinked' ), wfMsg( 'recentchangeslinked' ),
1250 'target=' . $wgTitle->getPrefixedURL() );
1251 }
1252 return $s;
1253 }
1254
1255 function otherLanguages()
1256 {
1257 global $wgOut, $wgLang, $wgTitle, $wgUseNewInterlanguage;
1258
1259 $a = $wgOut->getLanguageLinks();
1260 if ( 0 == count( $a ) ) {
1261 if ( !$wgUseNewInterlanguage ) return '';
1262 $ns = $wgLang->getNsIndex ( $wgTitle->getNamespace () ) ;
1263 if ( $ns != 0 AND $ns != 1 ) return '' ;
1264 $pn = 'Intl' ;
1265 $x = 'mode=addlink&xt='.$wgTitle->getDBkey() ;
1266 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
1267 wfMsg( 'intl' ) , $x );
1268 }
1269
1270 if ( !$wgUseNewInterlanguage ) {
1271 $s = wfMsg( 'otherlanguages' ) . ': ';
1272 } else {
1273 global $wgLanguageCode ;
1274 $x = 'mode=zoom&xt='.$wgTitle->getDBkey() ;
1275 $x .= '&xl='.$wgLanguageCode ;
1276 $s = $this->makeKnownLink( $wgLang->specialPage( 'Intl' ),
1277 wfMsg( 'otherlanguages' ) , $x ) . ': ' ;
1278 }
1279
1280 $s = wfMsg( 'otherlanguages' ) . ': ';
1281 $first = true;
1282 if($wgLang->isRTL()) $s .= '<span dir="LTR">';
1283 foreach( $a as $l ) {
1284 if ( ! $first ) { $s .= ' | '; }
1285 $first = false;
1286
1287 $nt = Title::newFromText( $l );
1288 $url = $nt->getFullURL();
1289 $text = $wgLang->getLanguageName( $nt->getInterwiki() );
1290
1291 if ( '' == $text ) { $text = $l; }
1292 $style = $this->getExternalLinkAttributes( $l, $text );
1293 $s .= "<a href=\"{$url}\"{$style}>{$text}</a>";
1294 }
1295 if($wgLang->isRTL()) $s .= '</span>';
1296 return $s;
1297 }
1298
1299 function bugReportsLink()
1300 {
1301 $s = $this->makeKnownLink( wfMsg( 'bugreportspage' ),
1302 wfMsg( 'bugreports' ) );
1303 return $s;
1304 }
1305
1306 function dateLink()
1307 {
1308 global $wgLinkCache;
1309 $t1 = Title::newFromText( gmdate( 'F j' ) );
1310 $t2 = Title::newFromText( gmdate( 'Y' ) );
1311
1312 $wgLinkCache->suspend();
1313 $id = $t1->getArticleID();
1314 $wgLinkCache->resume();
1315
1316 if ( 0 == $id ) {
1317 $s = $this->makeBrokenLink( $t1->getText() );
1318 } else {
1319 $s = $this->makeKnownLink( $t1->getText() );
1320 }
1321 $s .= ', ';
1322
1323 $wgLinkCache->suspend();
1324 $id = $t2->getArticleID();
1325 $wgLinkCache->resume();
1326
1327 if ( 0 == $id ) {
1328 $s .= $this->makeBrokenLink( $t2->getText() );
1329 } else {
1330 $s .= $this->makeKnownLink( $t2->getText() );
1331 }
1332 return $s;
1333 }
1334
1335 function talkLink()
1336 {
1337 global $wgLang, $wgTitle, $wgLinkCache;
1338
1339 $tns = $wgTitle->getNamespace();
1340 if ( -1 == $tns ) { return ''; }
1341
1342 $pn = $wgTitle->getText();
1343 $tp = wfMsg( 'talkpage' );
1344 if ( Namespace::isTalk( $tns ) ) {
1345 $lns = Namespace::getSubject( $tns );
1346 switch($tns) {
1347 case 1:
1348 $text = wfMsg('articlepage');
1349 break;
1350 case 3:
1351 $text = wfMsg('userpage');
1352 break;
1353 case 5:
1354 $text = wfMsg('wikipediapage');
1355 break;
1356 case 7:
1357 $text = wfMsg('imagepage');
1358 break;
1359 default:
1360 $text= wfMsg('articlepage');
1361 }
1362 } else {
1363
1364 $lns = Namespace::getTalk( $tns );
1365 $text=$tp;
1366 }
1367 $n = $wgLang->getNsText( $lns );
1368 if ( '' == $n ) { $link = $pn; }
1369 else { $link = $n.':'.$pn; }
1370
1371 $wgLinkCache->suspend();
1372 $s = $this->makeLink( $link, $text );
1373 $wgLinkCache->resume();
1374
1375 return $s;
1376 }
1377
1378 function commentLink()
1379 {
1380 global $wgLang, $wgTitle, $wgLinkCache;
1381
1382 $tns = $wgTitle->getNamespace();
1383 if ( -1 == $tns ) { return ''; }
1384
1385 $lns = ( Namespace::isTalk( $tns ) ) ? $tns : Namespace::getTalk( $tns );
1386
1387 # assert Namespace::isTalk( $lns )
1388
1389 $n = $wgLang->getNsText( $lns );
1390 $pn = $wgTitle->getText();
1391
1392 $link = $n.':'.$pn;
1393
1394 $wgLinkCache->suspend();
1395 $s = $this->makeKnownLink($link, wfMsg('postcomment'), 'action=edit&section=new');
1396 $wgLinkCache->resume();
1397
1398 return $s;
1399 }
1400
1401 # After all the page content is transformed into HTML, it makes
1402 # a final pass through here for things like table backgrounds.
1403 #
1404 function transformContent( $text )
1405 {
1406 return $text;
1407 }
1408
1409 # Note: This function MUST call getArticleID() on the link,
1410 # otherwise the cache won't get updated properly. See LINKCACHE.DOC.
1411 #
1412 function makeLink( $title, $text = '', $query = '', $trail = '' ) {
1413 wfProfileIn( 'Skin::makeLink' );
1414 $nt = Title::newFromText( $title );
1415 if ($nt) {
1416 $result = $this->makeLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1417 } else {
1418 wfDebug( 'Invalid title passed to Skin::makeLink(): "'.$title."\"\n" );
1419 $result = $text == "" ? $title : $text;
1420 }
1421
1422 wfProfileOut( 'Skin::makeLink' );
1423 return $result;
1424 }
1425
1426 function makeKnownLink( $title, $text = '', $query = '', $trail = '', $prefix = '',$aprops = '') {
1427 $nt = Title::newFromText( $title );
1428 if ($nt) {
1429 return $this->makeKnownLinkObj( Title::newFromText( $title ), $text, $query, $trail, $prefix , $aprops );
1430 } else {
1431 wfDebug( 'Invalid title passed to Skin::makeKnownLink(): "'.$title."\"\n" );
1432 return $text == '' ? $title : $text;
1433 }
1434 }
1435
1436 function makeBrokenLink( $title, $text = '', $query = '', $trail = '' ) {
1437 $nt = Title::newFromText( $title );
1438 if ($nt) {
1439 return $this->makeBrokenLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1440 } else {
1441 wfDebug( 'Invalid title passed to Skin::makeBrokenLink(): "'.$title."\"\n" );
1442 return $text == '' ? $title : $text;
1443 }
1444 }
1445
1446 function makeStubLink( $title, $text = '', $query = '', $trail = '' ) {
1447 $nt = Title::newFromText( $title );
1448 if ($nt) {
1449 return $this->makeStubLinkObj( Title::newFromText( $title ), $text, $query, $trail );
1450 } else {
1451 wfDebug( 'Invalid title passed to Skin::makeStubLink(): "'.$title."\"\n" );
1452 return $text == '' ? $title : $text;
1453 }
1454 }
1455
1456 # Pass a title object, not a title string
1457 function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
1458 {
1459 global $wgOut, $wgUser;
1460 $fname = 'Skin::makeLinkObj';
1461
1462 # Fail gracefully
1463 if ( ! isset($nt) )
1464 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1465
1466 if ( $nt->isExternal() ) {
1467 $u = $nt->getFullURL();
1468 $link = $nt->getPrefixedURL();
1469 if ( '' == $text ) { $text = $nt->getPrefixedText(); }
1470 $style = $this->getExternalLinkAttributes( $link, $text, 'extiw' );
1471
1472 $inside = '';
1473 if ( '' != $trail ) {
1474 if ( preg_match( '/^([a-z]+)(.*)$$/sD', $trail, $m ) ) {
1475 $inside = $m[1];
1476 $trail = $m[2];
1477 }
1478 }
1479 $retVal = "<a href=\"{$u}\"{$style}>{$text}{$inside}</a>{$trail}";
1480 } elseif ( 0 == $nt->getNamespace() && "" == $nt->getText() ) {
1481 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1482 } elseif ( ( -1 == $nt->getNamespace() ) ||
1483 ( Namespace::getImage() == $nt->getNamespace() ) ) {
1484 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1485 } else {
1486 if ( $this->postParseLinkColour() ) {
1487 $inside = '';
1488 if ( '' != $trail ) {
1489 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1490 $inside = $m[1];
1491 $trail = $m[2];
1492 }
1493 }
1494
1495 # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders()
1496 $retVal = '<!--LINK ' . implode( ' ', array( $nt->getNamespace(), $nt->getDBkey(),
1497 $query, $prefix . $text . $inside ) ) . "-->{$trail}";
1498 } else {
1499 # Work out link colour immediately
1500 $aid = $nt->getArticleID() ;
1501 if ( 0 == $aid ) {
1502 $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix );
1503 } else {
1504 $threshold = $wgUser->getOption('stubthreshold') ;
1505 if ( $threshold > 0 ) {
1506 $dbr =& wfGetDB( DB_SLAVE );
1507 $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace',
1508 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ;
1509 if ( $s !== false ) {
1510 $size = $s->x;
1511 if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) {
1512 $size = $threshold*2 ; # Really big
1513 }
1514 $dbr->freeResult( $res );
1515 } else {
1516 $size = $threshold*2 ; # Really big
1517 }
1518 } else {
1519 $size = 1 ;
1520 }
1521 if ( $size < $threshold ) {
1522 $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix );
1523 } else {
1524 $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix );
1525 }
1526 }
1527 }
1528 }
1529 return $retVal;
1530 }
1531
1532 # Pass a title object, not a title string
1533 function makeKnownLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' , $aprops = '')
1534 {
1535 global $wgOut, $wgTitle, $wgInputEncoding;
1536
1537 $fname = 'Skin::makeKnownLinkObj';
1538 wfProfileIn( $fname );
1539
1540 if ( !is_object( $nt ) ) {
1541 return $text;
1542 }
1543 $link = $nt->getPrefixedURL();
1544
1545 if ( '' == $link ) {
1546 $u = '';
1547 if ( '' == $text ) {
1548 $text = htmlspecialchars( $nt->getFragment() );
1549 }
1550 } else {
1551 $u = $nt->escapeLocalURL( $query );
1552 }
1553 if ( '' != $nt->getFragment() ) {
1554 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT, $wgInputEncoding ) );
1555 $replacearray = array(
1556 '%3A' => ':',
1557 '%' => '.'
1558 );
1559 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1560 }
1561 if ( '' == $text ) {
1562 $text = htmlspecialchars( $nt->getPrefixedText() );
1563 }
1564 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1565
1566 $inside = '';
1567 if ( '' != $trail ) {
1568 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1569 $inside = $m[1];
1570 $trail = $m[2];
1571 }
1572 }
1573 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1574 wfProfileOut( $fname );
1575 return $r;
1576 }
1577
1578 # Pass a title object, not a title string
1579 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1580 {
1581 global $wgOut, $wgUser;
1582
1583 $fname = 'Skin::makeBrokenLinkObj';
1584 wfProfileIn( $fname );
1585
1586 if ( '' == $query ) {
1587 $q = 'action=edit';
1588 } else {
1589 $q = 'action=edit&'.$query;
1590 }
1591 $u = $nt->escapeLocalURL( $q );
1592
1593 if ( '' == $text ) {
1594 $text = htmlspecialchars( $nt->getPrefixedText() );
1595 }
1596 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1597
1598 $inside = '';
1599 if ( '' != $trail ) {
1600 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1601 $inside = $m[1];
1602 $trail = $m[2];
1603 }
1604 }
1605 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1606 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1607 } else {
1608 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1609 }
1610
1611 wfProfileOut( $fname );
1612 return $s;
1613 }
1614
1615 # Pass a title object, not a title string
1616 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1617 {
1618 global $wgOut, $wgUser;
1619
1620 $link = $nt->getPrefixedURL();
1621
1622 $u = $nt->escapeLocalURL( $query );
1623
1624 if ( '' == $text ) {
1625 $text = htmlspecialchars( $nt->getPrefixedText() );
1626 }
1627 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1628
1629 $inside = '';
1630 if ( '' != $trail ) {
1631 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1632 $inside = $m[1];
1633 $trail = $m[2];
1634 }
1635 }
1636 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1637 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1638 } else {
1639 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1640 }
1641 return $s;
1642 }
1643
1644 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1645 {
1646 $u = $nt->escapeLocalURL( $query );
1647 if ( '' == $text ) {
1648 $text = htmlspecialchars( $nt->getPrefixedText() );
1649 }
1650 $inside = '';
1651 if ( '' != $trail ) {
1652 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1653 $inside = $m[1];
1654 $trail = $m[2];
1655 }
1656 }
1657 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1658 }
1659
1660 /* these are used extensively in SkinPHPTal, but also some other places */
1661 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1662 $title = Title::makeTitle( NS_SPECIAL, $name );
1663 $this->checkTitle($title, $name);
1664 return $title->getLocalURL( $urlaction );
1665 }
1666 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1667 $title = Title::newFromText( $name );
1668 $title = $title->getTalkPage();
1669 $this->checkTitle($title, $name);
1670 return $title->getLocalURL( $urlaction );
1671 }
1672 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1673 $title = Title::newFromText( $name );
1674 $title= $title->getSubjectPage();
1675 $this->checkTitle($title, $name);
1676 return $title->getLocalURL( $urlaction );
1677 }
1678 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1679 $title = Title::newFromText( wfMsg($name) );
1680 $this->checkTitle($title, $name);
1681 return $title->getLocalURL( $urlaction );
1682 }
1683 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1684 $title = Title::newFromText( $name );
1685 $this->checkTitle($title, $name);
1686 return $title->getLocalURL( $urlaction );
1687 }
1688 # this can be passed the NS number as defined in Language.php
1689 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1690 $title = Title::makeTitle( $namespace, $name );
1691 $this->checkTitle($title, $name);
1692 return $title->getLocalURL( $urlaction );
1693 }
1694
1695 /* these return an array with the 'href' and boolean 'exists' */
1696 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1697 $title = Title::newFromText( $name );
1698 $this->checkTitle($title, $name);
1699 return array(
1700 'href' => $title->getLocalURL( $urlaction ),
1701 'exists' => $title->getArticleID() != 0?true:false
1702 );
1703 }
1704 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1705 $title = Title::newFromText( $name );
1706 $title = $title->getTalkPage();
1707 $this->checkTitle($title, $name);
1708 return array(
1709 'href' => $title->getLocalURL( $urlaction ),
1710 'exists' => $title->getArticleID() != 0?true:false
1711 );
1712 }
1713 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1714 $title = Title::newFromText( $name );
1715 $title= $title->getSubjectPage();
1716 $this->checkTitle($title, $name);
1717 return array(
1718 'href' => $title->getLocalURL( $urlaction ),
1719 'exists' => $title->getArticleID() != 0?true:false
1720 );
1721 }
1722 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1723 $title = Title::newFromText( wfMsg($name) );
1724 $this->checkTitle($title, $name);
1725 return array(
1726 'href' => $title->getLocalURL( $urlaction ),
1727 'exists' => $title->getArticleID() != 0?true:false
1728 );
1729 }
1730
1731 # make sure we have some title to operate on
1732 /*static*/ function checkTitle ( &$title, &$name ) {
1733 if(!is_object($title)) {
1734 $title = Title::newFromText( $name );
1735 if(!is_object($title)) {
1736 $title = Title::newFromText( '--error: link target missing--' );
1737 }
1738 }
1739 }
1740
1741 function fnamePart( $url )
1742 {
1743 $basename = strrchr( $url, '/' );
1744 if ( false === $basename ) {
1745 $basename = $url;
1746 } else {
1747 $basename = substr( $basename, 1 );
1748 }
1749 return htmlspecialchars( $basename );
1750 }
1751
1752 function makeImage( $url, $alt = '' )
1753 {
1754 global $wgOut;
1755
1756 if ( '' == $alt ) {
1757 $alt = $this->fnamePart( $url );
1758 }
1759 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1760 return $s;
1761 }
1762
1763 function makeImageLink( $name, $url, $alt = '' ) {
1764 $nt = Title::makeTitle( Namespace::getImage(), $name );
1765 return $this->makeImageLinkObj( $nt, $alt );
1766 }
1767
1768 function makeImageLinkObj( $nt, $alt = '' ) {
1769 global $wgLang, $wgUseImageResize;
1770 $img = Image::newFromTitle( $nt );
1771 $url = $img->getURL();
1772
1773 $align = '';
1774 $prefix = $postfix = '';
1775
1776 if ( $wgUseImageResize ) {
1777 # Check if the alt text is of the form "options|alt text"
1778 # Options are:
1779 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1780 # * left no resizing, just left align. label is used for alt= only
1781 # * right same, but right aligned
1782 # * none same, but not aligned
1783 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1784 # * center center the image
1785 # * framed Keep original image size, no magnify-button.
1786
1787 $part = explode( '|', $alt);
1788
1789 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1790 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1791 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1792 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1793 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1794 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1795 $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
1796 $alt = $part[count($part)-1];
1797
1798 $height = $framed = $thumb = false;
1799 $manual_thumb = "" ;
1800
1801 foreach( $part as $key => $val ) {
1802 $val_parts = explode ( "=" , $val , 2 ) ;
1803 $left_part = array_shift ( $val_parts ) ;
1804 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1805 $thumb=true;
1806 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1807 # use manually specified thumbnail
1808 $thumb=true;
1809 $manual_thumb = array_shift ( $val_parts ) ;
1810 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1811 # remember to set an alignment, don't render immediately
1812 $align = 'right';
1813 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1814 # remember to set an alignment, don't render immediately
1815 $align = 'left';
1816 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1817 # remember to set an alignment, don't render immediately
1818 $align = 'center';
1819 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1820 # remember to set an alignment, don't render immediately
1821 $align = 'none';
1822 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1823 # $match is the image width in pixels
1824 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1825 $width = intval( $m[1] );
1826 $height = intval( $m[2] );
1827 } else {
1828 $width = intval($match);
1829 }
1830 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1831 $framed=true;
1832 }
1833 }
1834 if ( 'center' == $align )
1835 {
1836 $prefix = '<span style="text-align: center">';
1837 $postfix = '</span>';
1838 $align = 'none';
1839 }
1840
1841 if ( $thumb || $framed ) {
1842
1843 # Create a thumbnail. Alignment depends on language
1844 # writing direction, # right aligned for left-to-right-
1845 # languages ("Western languages"), left-aligned
1846 # for right-to-left-languages ("Semitic languages")
1847 #
1848 # If thumbnail width has not been provided, it is set
1849 # here to 180 pixels
1850 if ( $align == '' ) {
1851 $align = $wgLang->isRTL() ? 'left' : 'right';
1852 }
1853 if ( ! isset($width) ) {
1854 $width = 180;
1855 }
1856 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1857
1858 } elseif ( isset($width) ) {
1859
1860 # Create a resized image, without the additional thumbnail
1861 # features
1862
1863 if ( ( ! $height === false )
1864 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1865 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1866 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1867 $width = $img->getWidth() * $height / $img->getHeight();
1868 }
1869 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1870 }
1871 } # endif $wgUseImageResize
1872
1873 if ( empty( $alt ) ) {
1874 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1875 }
1876 $alt = htmlspecialchars( $alt );
1877
1878 $u = $nt->escapeLocalURL();
1879 if ( $url == '' )
1880 {
1881 $s = wfMsg( 'missingimage', $img->getName() );
1882 $s .= "<br>{$alt}<br>{$url}<br>\n";
1883 } else {
1884 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1885 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1886 }
1887 if ( '' != $align ) {
1888 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1889 }
1890 return str_replace("\n", ' ',$prefix.$s.$postfix);
1891 }
1892
1893 # Make HTML for a thumbnail including image, border and caption
1894 # $img is an Image object
1895 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1896 global $wgStylePath, $wgLang;
1897 # $image = Title::makeTitle( Namespace::getImage(), $name );
1898 $url = $img->getURL();
1899
1900 #$label = htmlspecialchars( $label );
1901 $alt = preg_replace( '/<[^>]*>/', '', $label);
1902 $alt = htmlspecialchars( $alt );
1903
1904 $width = $height = 0;
1905 if ( $img->exists() )
1906 {
1907 $width = $img->getWidth();
1908 $height = $img->getHeight();
1909 }
1910 if ( 0 == $width || 0 == $height )
1911 {
1912 $width = $height = 200;
1913 }
1914 if ( $boxwidth == 0 )
1915 {
1916 $boxwidth = 200;
1917 }
1918 if ( $framed )
1919 {
1920 // Use image dimensions, don't scale
1921 $boxwidth = $width;
1922 $oboxwidth = $boxwidth + 2;
1923 $boxheight = $height;
1924 $thumbUrl = $url;
1925 } else {
1926 $h = intval( $height/($width/$boxwidth) );
1927 $oboxwidth = $boxwidth + 2;
1928 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1929 {
1930 $boxwidth *= $boxheight/$h;
1931 } else {
1932 $boxheight = $h;
1933 }
1934 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1935 }
1936
1937 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1938 {
1939 $manual_title = Title::makeTitle( Namespace::getImage(), $manual_thumb ); #new Title ( $manual_thumb ) ;
1940 $manual_img = Image::newFromTitle( $manual_title );
1941 $thumbUrl = $manual_img->getURL();
1942 if ( $manual_img->exists() )
1943 {
1944 $width = $manual_img->getWidth();
1945 $height = $manual_img->getHeight();
1946 $boxwidth = $width ;
1947 $boxheight = $height ;
1948 $oboxwidth = $boxwidth + 2 ;
1949 }
1950 }
1951
1952 $u = $img->getEscapeLocalURL();
1953
1954 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1955 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1956 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1957
1958 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1959 if ( $thumbUrl == '' ) {
1960 $s .= wfMsg( 'missingimage', $img->getName() );
1961 $zoomicon = '';
1962 } else {
1963 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1964 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1965 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1966 if ( $framed ) {
1967 $zoomicon="";
1968 } else {
1969 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1970 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1971 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1972 'width="15" height="11" alt="'.$more.'" /></a></div>';
1973 }
1974 }
1975 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1976 return str_replace("\n", ' ', $s);
1977 }
1978
1979 function makeMediaLink( $name, $url, $alt = "" ) {
1980 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1981 return $this->makeMediaLinkObj( $nt, $alt );
1982 }
1983
1984 function makeMediaLinkObj( $nt, $alt = "" )
1985 {
1986 if ( ! isset( $nt ) )
1987 {
1988 ### HOTFIX. Instead of breaking, return empty string.
1989 $s = $alt;
1990 } else {
1991 $name = $nt->getDBKey();
1992 $url = Image::wfImageUrl( $name );
1993 if ( empty( $alt ) ) {
1994 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1995 }
1996
1997 $u = htmlspecialchars( $url );
1998 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1999 }
2000 return $s;
2001 }
2002
2003 function specialLink( $name, $key = "" )
2004 {
2005 global $wgLang;
2006
2007 if ( '' == $key ) { $key = strtolower( $name ); }
2008 $pn = $wgLang->ucfirst( $name );
2009 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2010 wfMsg( $key ) );
2011 }
2012
2013 function makeExternalLink( $url, $text, $escape = true ) {
2014 $style = $this->getExternalLinkAttributes( $url, $text );
2015 $url = htmlspecialchars( $url );
2016 if( $escape ) {
2017 $text = htmlspecialchars( $text );
2018 }
2019 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2020 }
2021
2022 # Called by history lists and recent changes
2023 #
2024
2025 # Returns text for the start of the tabular part of RC
2026 function beginRecentChangesList()
2027 {
2028 $this->rc_cache = array() ;
2029 $this->rcMoveIndex = 0;
2030 $this->rcCacheIndex = 0 ;
2031 $this->lastdate = '';
2032 $this->rclistOpen = false;
2033 return '';
2034 }
2035
2036 function beginImageHistoryList()
2037 {
2038 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2039 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2040 return $s;
2041 }
2042
2043 # Returns text for the end of RC
2044 # If enhanced RC is in use, returns pretty much all the text
2045 function endRecentChangesList()
2046 {
2047 $s = $this->recentChangesBlock() ;
2048 if( $this->rclistOpen ) {
2049 $s .= "</ul>\n";
2050 }
2051 return $s;
2052 }
2053
2054 # Enhanced RC ungrouped line
2055 function recentChangesBlockLine ( $rcObj )
2056 {
2057 global $wgStylePath, $wgLang ;
2058
2059 # Get rc_xxxx variables
2060 extract( $rcObj->mAttribs ) ;
2061 $curIdEq = 'curid='.$rc_cur_id;
2062
2063 # Spacer image
2064 $r = '' ;
2065
2066 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2067 $r .= '<tt>' ;
2068
2069 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2070 $r .= '&nbsp;&nbsp;';
2071 } else {
2072 # M & N (minor & new)
2073 $M = wfMsg( 'minoreditletter' );
2074 $N = wfMsg( 'newpageletter' );
2075
2076 if ( $rc_type == RC_NEW ) {
2077 $r .= $N ;
2078 } else {
2079 $r .= '&nbsp;' ;
2080 }
2081 if ( $rc_minor ) {
2082 $r .= $M ;
2083 } else {
2084 $r .= '&nbsp;' ;
2085 }
2086 }
2087
2088 # Timestamp
2089 $r .= ' '.$rcObj->timestamp.' ' ;
2090 $r .= '</tt>' ;
2091
2092 # Article link
2093 $link = $rcObj->link ;
2094 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2095 $r .= $link ;
2096
2097 # Diff
2098 $r .= ' (' ;
2099 $r .= $rcObj->difflink ;
2100 $r .= '; ' ;
2101
2102 # Hist
2103 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2104
2105 # User/talk
2106 $r .= ') . . '.$rcObj->userlink ;
2107 $r .= $rcObj->usertalklink ;
2108
2109 # Comment
2110 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2111 $rc_comment=$this->formatComment($rc_comment);
2112 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2113 }
2114
2115 $r .= "<br />\n" ;
2116 return $r ;
2117 }
2118
2119 # Enhanced RC group
2120 function recentChangesBlockGroup ( $block )
2121 {
2122 global $wgStylePath, $wgLang ;
2123
2124 $r = '' ;
2125 $M = wfMsg( 'minoreditletter' );
2126 $N = wfMsg( 'newpageletter' );
2127
2128 # Collate list of users
2129 $isnew = false ;
2130 $userlinks = array () ;
2131 foreach ( $block AS $rcObj ) {
2132 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2133 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2134 $u = $rcObj->userlink ;
2135 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2136 $userlinks[$u]++ ;
2137 }
2138
2139 # Sort the list and convert to text
2140 krsort ( $userlinks ) ;
2141 asort ( $userlinks ) ;
2142 $users = array () ;
2143 foreach ( $userlinks as $userlink => $count) {
2144 $text = $userlink ;
2145 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2146 array_push ( $users , $text ) ;
2147 }
2148 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2149
2150 # Arrow
2151 $rci = 'RCI'.$this->rcCacheIndex ;
2152 $rcl = 'RCL'.$this->rcCacheIndex ;
2153 $rcm = 'RCM'.$this->rcCacheIndex ;
2154 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2155 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2156 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2157 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2158 $r .= $tl ;
2159
2160 # Main line
2161 # M/N
2162 $r .= '<tt>' ;
2163 if ( $isnew ) $r .= $N ;
2164 else $r .= '&nbsp;' ;
2165 $r .= '&nbsp;' ; # Minor
2166
2167 # Timestamp
2168 $r .= ' '.$block[0]->timestamp.' ' ;
2169 $r .= '</tt>' ;
2170
2171 # Article link
2172 $link = $block[0]->link ;
2173 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2174 $r .= $link ;
2175
2176 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2177 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2178 # Changes
2179 $r .= ' ('.count($block).' ' ;
2180 if ( $isnew ) $r .= wfMsg('changes');
2181 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2182 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2183 $r .= '; ' ;
2184
2185 # History
2186 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2187 $r .= ')' ;
2188 }
2189
2190 $r .= $users ;
2191 $r .= "<br />\n" ;
2192
2193 # Sub-entries
2194 $r .= '<div id="'.$rci.'" style="display:none">' ;
2195 foreach ( $block AS $rcObj ) {
2196 # Get rc_xxxx variables
2197 extract( $rcObj->mAttribs );
2198
2199 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2200 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2201 if ( $rc_new ) $r .= $N ;
2202 else $r .= '&nbsp;' ;
2203 if ( $rc_minor ) $r .= $M ;
2204 else $r .= '&nbsp;' ;
2205 $r .= '</tt>' ;
2206
2207 $o = '' ;
2208 if ( $rc_last_oldid != 0 ) {
2209 $o = 'oldid='.$rc_last_oldid ;
2210 }
2211 if ( $rc_type == RC_LOG ) {
2212 $link = $rcObj->timestamp ;
2213 } else {
2214 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2215 }
2216 $link = '<tt>'.$link.'</tt>' ;
2217
2218 $r .= $link ;
2219 $r .= ' (' ;
2220 $r .= $rcObj->curlink ;
2221 $r .= '; ' ;
2222 $r .= $rcObj->lastlink ;
2223 $r .= ') . . '.$rcObj->userlink ;
2224 $r .= $rcObj->usertalklink ;
2225 if ( $rc_comment != '' ) {
2226 $rc_comment=$this->formatComment($rc_comment);
2227 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2228 }
2229 $r .= "<br />\n" ;
2230 }
2231 $r .= "</div>\n" ;
2232
2233 $this->rcCacheIndex++ ;
2234 return $r ;
2235 }
2236
2237 # If enhanced RC is in use, this function takes the previously cached
2238 # RC lines, arranges them, and outputs the HTML
2239 function recentChangesBlock ()
2240 {
2241 global $wgStylePath ;
2242 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2243 $blockOut = '';
2244 foreach ( $this->rc_cache AS $secureName => $block ) {
2245 if ( count ( $block ) < 2 ) {
2246 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2247 } else {
2248 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2249 }
2250 }
2251
2252 return '<div>'.$blockOut.'</div>' ;
2253 }
2254
2255 # Called in a loop over all displayed RC entries
2256 # Either returns the line, or caches it for later use
2257 function recentChangesLine( &$rc, $watched = false )
2258 {
2259 global $wgUser ;
2260 $usenew = $wgUser->getOption( 'usenewrc' );
2261 if ( $usenew )
2262 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2263 else
2264 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2265 return $line ;
2266 }
2267
2268 function recentChangesLineOld( &$rc, $watched = false )
2269 {
2270 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2271
2272 # Extract DB fields into local scope
2273 extract( $rc->mAttribs );
2274 $curIdEq = 'curid=' . $rc_cur_id;
2275
2276 # Make date header if necessary
2277 $date = $wgLang->date( $rc_timestamp, true);
2278 $s = '';
2279 if ( $date != $this->lastdate ) {
2280 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2281 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2282 $this->lastdate = $date;
2283 $this->rclistOpen = true;
2284 }
2285
2286 # If this edit has not yet been patrolled, make it stick out
2287 $s .= ( ! $wgUseRCPatrol || $rc_patrolled ) ? '<li> ' : '<li class="not_patrolled"> ';
2288
2289 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2290 # Diff
2291 $s .= '(' . wfMsg( 'diff' ) . ') (';
2292 # Hist
2293 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2294 ') . . ';
2295
2296 # "[[x]] moved to [[y]]"
2297 $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
2298 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2299 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2300 } else {
2301 # Diff link
2302 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2303 $diffLink = wfMsg( 'diff' );
2304 } else {
2305 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2306 ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2307 $rcidparam = "&rcid={$rc_id}";
2308 else
2309 $rcidparam = "";
2310 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2311 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2312 '', '', ' tabindex="'.$rc->counter.'"');
2313 }
2314 $s .= '('.$diffLink.') (';
2315
2316 # History link
2317 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2318 $s .= ') . . ';
2319
2320 # M and N (minor and new)
2321 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2322 if ( $rc_type == RC_NEW ) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2323
2324 # Article link
2325 # If it's a new article, there is no diff link, but if it hasn't been
2326 # patrolled yet, we need to give users a way to do so
2327 if ( $wgUseRCPatrol && $rc_type == RC_NEW && $rc_patrolled == 0 &&
2328 $wgUser->getID() != 0 && ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2329 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2330 else
2331 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2332
2333 if ( $watched ) {
2334 $articleLink = '<strong>'.$articleLink.'</strong>';
2335 }
2336 $s .= ' '.$articleLink;
2337
2338 }
2339
2340 # Timestamp
2341 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2342
2343 # User link (or contributions for unregistered users)
2344 if ( 0 == $rc_user ) {
2345 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2346 $rc_user_text, 'target=' . $rc_user_text );
2347 } else {
2348 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2349 }
2350 $s .= $userLink;
2351
2352 # User talk link
2353 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2354 global $wgDisableAnonTalk;
2355 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2356 $userTalkLink = '';
2357 } else {
2358 $utns=$wgLang->getNsText(NS_USER_TALK);
2359 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2360 }
2361 # Block link
2362 $blockLink='';
2363 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2364 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2365 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2366
2367 }
2368 if($blockLink) {
2369 if($userTalkLink) $userTalkLink .= ' | ';
2370 $userTalkLink .= $blockLink;
2371 }
2372 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2373
2374 # Add comment
2375 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2376 $rc_comment=$this->formatComment($rc_comment);
2377 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2378 }
2379 $s .= "</li>\n";
2380
2381 return $s;
2382 }
2383
2384 function recentChangesLineNew( &$baseRC, $watched = false )
2385 {
2386 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2387
2388 # Create a specialised object
2389 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2390
2391 # Extract fields from DB into the function scope (rc_xxxx variables)
2392 extract( $rc->mAttribs );
2393 $curIdEq = 'curid=' . $rc_cur_id;
2394
2395 # If it's a new day, add the headline and flush the cache
2396 $date = $wgLang->date( $rc_timestamp, true);
2397 $ret = '';
2398 if ( $date != $this->lastdate ) {
2399 # Process current cache
2400 $ret = $this->recentChangesBlock () ;
2401 $this->rc_cache = array() ;
2402 $ret .= "<h4>{$date}</h4>\n";
2403 $this->lastdate = $date;
2404 }
2405
2406 # Make article link
2407 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2408 $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
2409 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2410 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2411 } else {
2412 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2413 }
2414
2415 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2416 $rc->watched = $watched ;
2417 $rc->link = $clink ;
2418 $rc->timestamp = $time;
2419
2420 # Make "cur" and "diff" links
2421 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2422 $curLink = wfMsg( 'cur' );
2423 $diffLink = wfMsg( 'diff' );
2424 } else {
2425 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2426 $aprops = ' tabindex="'.$baseRC->counter.'"';
2427 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2428 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2429 }
2430
2431 # Make "last" link
2432 $titleObj = $rc->getTitle();
2433 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2434 $lastLink = wfMsg( 'last' );
2435 } else {
2436 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2437 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2438 }
2439
2440 # Make user link (or user contributions for unregistered users)
2441 if ( $rc_user == 0 ) {
2442 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2443 $rc_user_text, 'target=' . $rc_user_text );
2444 } else {
2445 $userLink = $this->makeLink( $wgLang->getNsText(
2446 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2447 }
2448
2449 $rc->userlink = $userLink;
2450 $rc->lastlink = $lastLink;
2451 $rc->curlink = $curLink;
2452 $rc->difflink = $diffLink;
2453
2454 # Make user talk link
2455 $utns=$wgLang->getNsText(NS_USER_TALK);
2456 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2457 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2458
2459 global $wgDisableAnonTalk;
2460 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2461 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2462 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2463 if( $wgDisableAnonTalk )
2464 $rc->usertalklink = ' ('.$blockLink.')';
2465 else
2466 $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
2467 } else {
2468 if( $wgDisableAnonTalk && ($rc_user == 0) )
2469 $rc->usertalklink = '';
2470 else
2471 $rc->usertalklink = ' ('.$userTalkLink.')';
2472 }
2473
2474 # Put accumulated information into the cache, for later display
2475 # Page moves go on their own line
2476 $title = $rc->getTitle();
2477 $secureName = $title->getPrefixedDBkey();
2478 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2479 # Use an @ character to prevent collision with page names
2480 $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
2481 } else {
2482 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2483 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2484 }
2485 return $ret;
2486 }
2487
2488 function endImageHistoryList()
2489 {
2490 $s = "</ul>\n";
2491 return $s;
2492 }
2493
2494 /* This function is called by all recent changes variants, by the page history,
2495 and by the user contributions list. It is responsible for formatting edit
2496 comments. It escapes any HTML in the comment, but adds some CSS to format
2497 auto-generated comments (from section editing) and formats [[wikilinks]].
2498 Main author: Erik Möller (moeller@scireview.de)
2499 */
2500 function formatComment($comment)
2501 {
2502 global $wgLang;
2503 $comment = htmlspecialchars( $comment );
2504
2505 # The pattern for autogen comments is / * foo * /, which makes for
2506 # some nasty regex.
2507 # We look for all comments, match any text before and after the comment,
2508 # add a separator where needed and format the comment itself with CSS
2509 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2510 $pre=$match[1];
2511 $auto=$match[2];
2512 $post=$match[3];
2513 $sep='-';
2514 if($pre) { $auto = $sep.' '.$auto; }
2515 if($post) { $auto .= ' '.$sep; }
2516 $auto='<span class="autocomment">'.$auto.'</span>';
2517 $comment=$pre.$auto.$post;
2518 }
2519
2520 # format regular and media links - all other wiki formatting
2521 # is ignored
2522 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2523 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2524 # Handle link renaming [[foo|text]] will show link as "text"
2525 if( "" != $match[3] ) {
2526 $text = $match[3];
2527 } else {
2528 $text = $match[1];
2529 }
2530 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2531 # Media link; trail not supported.
2532 $linkRegexp = '/\[\[(.*?)\]\]/';
2533 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2534 } else {
2535 # Other kind of link
2536 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2537 $trail = $submatch[1];
2538 } else {
2539 $trail = "";
2540 }
2541 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2542 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2543 }
2544 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2545 }
2546 return $comment;
2547 }
2548
2549 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2550 {
2551 global $wgUser, $wgLang, $wgTitle;
2552
2553 $datetime = $wgLang->timeanddate( $timestamp, true );
2554 $del = wfMsg( 'deleteimg' );
2555 $delall = wfMsg( 'deleteimgcompletely' );
2556 $cur = wfMsg( 'cur' );
2557
2558 if ( $iscur ) {
2559 $url = Image::wfImageUrl( $img );
2560 $rlink = $cur;
2561 if ( $wgUser->isSysop() ) {
2562 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2563 '&action=delete' );
2564 $style = $this->getInternalLinkAttributes( $link, $delall );
2565
2566 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2567 } else {
2568 $dlink = $del;
2569 }
2570 } else {
2571 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2572 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2573 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2574 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2575 urlencode( $img ) );
2576 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2577 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2578 } else {
2579 # Having live active links for non-logged in users
2580 # means that bots and spiders crawling our site can
2581 # inadvertently change content. Baaaad idea.
2582 $rlink = wfMsg( 'revertimg' );
2583 $dlink = $del;
2584 }
2585 }
2586 if ( 0 == $user ) {
2587 $userlink = $usertext;
2588 } else {
2589 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2590 ':'.$usertext, $usertext );
2591 }
2592 $nbytes = wfMsg( 'nbytes', $size );
2593 $style = $this->getInternalLinkAttributes( $url, $datetime );
2594
2595 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2596 . " . . {$userlink} ({$nbytes})";
2597
2598 if ( '' != $description && '*' != $description ) {
2599 $sk=$wgUser->getSkin();
2600 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2601 }
2602 $s .= "</li>\n";
2603 return $s;
2604 }
2605
2606 function tocIndent($level) {
2607 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2608 }
2609
2610 function tocUnindent($level) {
2611 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2612 }
2613
2614 # parameter level defines if we are on an indentation level
2615 function tocLine( $anchor, $tocline, $level ) {
2616 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2617 if($level) {
2618 return $link."\n";
2619 } else {
2620 return '<div class="tocline">'.$link."</div>\n";
2621 }
2622
2623 }
2624
2625 function tocTable($toc) {
2626 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2627 # try min-width & co when somebody gets a chance
2628 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2629 return
2630 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2631 '<b>'.wfMsg('toc').'</b>' .
2632 $hideline .
2633 '</td></tr><tr id="tocinside"><td>'."\n".
2634 $toc."</td></tr></table>\n";
2635 }
2636
2637 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2638 function editSectionScript( $section, $head ) {
2639 global $wgTitle, $wgRequest;
2640 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2641 return $head;
2642 }
2643 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2644 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2645 }
2646
2647 function editSectionLink( $section ) {
2648 global $wgRequest;
2649 global $wgTitle, $wgUser, $wgLang;
2650
2651 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2652 # Section edit links would be out of sync on an old page.
2653 # But, if we're diffing to the current page, they'll be
2654 # correct.
2655 return '';
2656 }
2657
2658 $editurl = '&section='.$section;
2659 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2660
2661 if( $wgLang->isRTL() ) {
2662 $farside = 'left';
2663 $nearside = 'right';
2664 } else {
2665 $farside = 'right';
2666 $nearside = 'left';
2667 }
2668 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2669
2670 }
2671
2672 // This function is called by EditPage.php and shows a bulletin board style
2673 // toolbar for common editing functions. It can be disabled in the user preferences.
2674 // The necsesary JavaScript code can be found in style/wikibits.js.
2675 function getEditToolbar() {
2676 global $wgStylePath, $wgLang, $wgMimeType;
2677
2678 // toolarray an array of arrays which each include the filename of
2679 // the button image (without path), the opening tag, the closing tag,
2680 // and optionally a sample text that is inserted between the two when no
2681 // selection is highlighted.
2682 // The tip text is shown when the user moves the mouse over the button.
2683
2684 // Already here are accesskeys (key), which are not used yet until someone
2685 // can figure out a way to make them work in IE. However, we should make
2686 // sure these keys are not defined on the edit page.
2687 $toolarray=array(
2688 array( 'image'=>'button_bold.png',
2689 'open'=>"\'\'\'",
2690 'close'=>"\'\'\'",
2691 'sample'=>wfMsg('bold_sample'),
2692 'tip'=>wfMsg('bold_tip'),
2693 'key'=>'B'
2694 ),
2695 array( "image"=>"button_italic.png",
2696 "open"=>"\'\'",
2697 "close"=>"\'\'",
2698 "sample"=>wfMsg("italic_sample"),
2699 "tip"=>wfMsg("italic_tip"),
2700 "key"=>"I"
2701 ),
2702 array( "image"=>"button_link.png",
2703 "open"=>"[[",
2704 "close"=>"]]",
2705 "sample"=>wfMsg("link_sample"),
2706 "tip"=>wfMsg("link_tip"),
2707 "key"=>"L"
2708 ),
2709 array( "image"=>"button_extlink.png",
2710 "open"=>"[",
2711 "close"=>"]",
2712 "sample"=>wfMsg("extlink_sample"),
2713 "tip"=>wfMsg("extlink_tip"),
2714 "key"=>"X"
2715 ),
2716 array( "image"=>"button_headline.png",
2717 "open"=>"\\n== ",
2718 "close"=>" ==\\n",
2719 "sample"=>wfMsg("headline_sample"),
2720 "tip"=>wfMsg("headline_tip"),
2721 "key"=>"H"
2722 ),
2723 array( "image"=>"button_image.png",
2724 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2725 "close"=>"]]",
2726 "sample"=>wfMsg("image_sample"),
2727 "tip"=>wfMsg("image_tip"),
2728 "key"=>"D"
2729 ),
2730 array( "image"=>"button_media.png",
2731 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2732 "close"=>"]]",
2733 "sample"=>wfMsg("media_sample"),
2734 "tip"=>wfMsg("media_tip"),
2735 "key"=>"M"
2736 ),
2737 array( "image"=>"button_math.png",
2738 "open"=>"\\<math\\>",
2739 "close"=>"\\</math\\>",
2740 "sample"=>wfMsg("math_sample"),
2741 "tip"=>wfMsg("math_tip"),
2742 "key"=>"C"
2743 ),
2744 array( "image"=>"button_nowiki.png",
2745 "open"=>"\\<nowiki\\>",
2746 "close"=>"\\</nowiki\\>",
2747 "sample"=>wfMsg("nowiki_sample"),
2748 "tip"=>wfMsg("nowiki_tip"),
2749 "key"=>"N"
2750 ),
2751 array( "image"=>"button_sig.png",
2752 "open"=>"--~~~~",
2753 "close"=>"",
2754 "sample"=>"",
2755 "tip"=>wfMsg("sig_tip"),
2756 "key"=>"Y"
2757 ),
2758 array( "image"=>"button_hr.png",
2759 "open"=>"\\n----\\n",
2760 "close"=>"",
2761 "sample"=>"",
2762 "tip"=>wfMsg("hr_tip"),
2763 "key"=>"R"
2764 )
2765 );
2766 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2767
2768 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2769 foreach($toolarray as $tool) {
2770
2771 $image=$wgStylePath.'/images/'.$tool['image'];
2772 $open=$tool['open'];
2773 $close=$tool['close'];
2774 $sample = addslashes( $tool['sample'] );
2775
2776 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2777 // Older browsers show a "speedtip" type message only for ALT.
2778 // Ideally these should be different, realistically they
2779 // probably don't need to be.
2780 $tip = addslashes( $tool['tip'] );
2781
2782 #$key = $tool["key"];
2783
2784 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2785 }
2786
2787 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2788 $toolbar.="document.writeln(\"</div>\");\n";
2789
2790 $toolbar.="/*]]>*/\n</script>";
2791 return $toolbar;
2792 }
2793
2794 /* public */ function suppressUrlExpansion() {
2795 return false;
2796 }
2797 }
2798
2799 }
2800 ?>