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