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