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