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