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