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