Prevent division-by-zero-errors. BUG#1007562
[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 $width = $height = 0;
1895 if ( $img->exists() )
1896 {
1897 $width = $img->getWidth();
1898 $height = $img->getHeight();
1899 }
1900 if ( 0 == $width || 0 == $height )
1901 {
1902 $width = $height = 200;
1903 }
1904 if ( $boxwidth == 0 )
1905 {
1906 $boxwidth = 200;
1907 }
1908 if ( $framed )
1909 {
1910 // Use image dimensions, don't scale
1911 $boxwidth = $width;
1912 $oboxwidth = $boxwidth + 2;
1913 $boxheight = $height;
1914 $thumbUrl = $url;
1915 } else {
1916 $h = intval( $height/($width/$boxwidth) );
1917 $oboxwidth = $boxwidth + 2;
1918 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1919 {
1920 $boxwidth *= $boxheight/$h;
1921 } else {
1922 $boxheight = $h;
1923 }
1924 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1925 }
1926
1927 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1928 {
1929 $manual_title = Title::makeTitle( Namespace::getImage(), $manual_thumb ); #new Title ( $manual_thumb ) ;
1930 $manual_img = Image::newFromTitle( $manual_title );
1931 $thumbUrl = $manual_img->getURL();
1932 if ( $manual_img->exists() )
1933 {
1934 $width = $manual_img->getWidth();
1935 $height = $manual_img->getHeight();
1936 $boxwidth = $width ;
1937 $boxheight = $height ;
1938 $oboxwidth = $boxwidth + 2 ;
1939 }
1940 }
1941
1942 $u = $img->getEscapeLocalURL();
1943
1944 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1945 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1946 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1947
1948 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1949 if ( $thumbUrl == '' ) {
1950 $s .= wfMsg( 'missingimage', $img->getName() );
1951 $zoomicon = '';
1952 } else {
1953 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
1954 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
1955 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
1956 if ( $framed ) {
1957 $zoomicon="";
1958 } else {
1959 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
1960 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
1961 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
1962 'width="15" height="11" alt="'.$more.'" /></a></div>';
1963 }
1964 }
1965 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
1966 return str_replace("\n", ' ', $s);
1967 }
1968
1969 function makeMediaLink( $name, $url, $alt = "" ) {
1970 $nt = Title::makeTitle( Namespace::getMedia(), $name );
1971 return $this->makeMediaLinkObj( $nt, $alt );
1972 }
1973
1974 function makeMediaLinkObj( $nt, $alt = "" )
1975 {
1976 if ( ! isset( $nt ) )
1977 {
1978 ### HOTFIX. Instead of breaking, return empty string.
1979 $s = $alt;
1980 } else {
1981 $name = $nt->getDBKey();
1982 $url = Image::wfImageUrl( $name );
1983 if ( empty( $alt ) ) {
1984 $alt = preg_replace( '/\.(.+?)^/', '', $name );
1985 }
1986
1987 $u = htmlspecialchars( $url );
1988 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
1989 }
1990 return $s;
1991 }
1992
1993 function specialLink( $name, $key = "" )
1994 {
1995 global $wgLang;
1996
1997 if ( '' == $key ) { $key = strtolower( $name ); }
1998 $pn = $wgLang->ucfirst( $name );
1999 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2000 wfMsg( $key ) );
2001 }
2002
2003 function makeExternalLink( $url, $text, $escape = true ) {
2004 $style = $this->getExternalLinkAttributes( $url, $text );
2005 $url = htmlspecialchars( $url );
2006 if( $escape ) {
2007 $text = htmlspecialchars( $text );
2008 }
2009 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2010 }
2011
2012 # Called by history lists and recent changes
2013 #
2014
2015 # Returns text for the start of the tabular part of RC
2016 function beginRecentChangesList()
2017 {
2018 $this->rc_cache = array() ;
2019 $this->rcMoveIndex = 0;
2020 $this->rcCacheIndex = 0 ;
2021 $this->lastdate = '';
2022 $this->rclistOpen = false;
2023 return '';
2024 }
2025
2026 function beginImageHistoryList()
2027 {
2028 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2029 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2030 return $s;
2031 }
2032
2033 # Returns text for the end of RC
2034 # If enhanced RC is in use, returns pretty much all the text
2035 function endRecentChangesList()
2036 {
2037 $s = $this->recentChangesBlock() ;
2038 if( $this->rclistOpen ) {
2039 $s .= "</ul>\n";
2040 }
2041 return $s;
2042 }
2043
2044 # Enhanced RC ungrouped line
2045 function recentChangesBlockLine ( $rcObj )
2046 {
2047 global $wgStylePath, $wgLang ;
2048
2049 # Get rc_xxxx variables
2050 extract( $rcObj->mAttribs ) ;
2051 $curIdEq = 'curid='.$rc_cur_id;
2052
2053 # Spacer image
2054 $r = '' ;
2055
2056 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2057 $r .= '<tt>' ;
2058
2059 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2060 $r .= '&nbsp;&nbsp;';
2061 } else {
2062 # M & N (minor & new)
2063 $M = wfMsg( 'minoreditletter' );
2064 $N = wfMsg( 'newpageletter' );
2065
2066 if ( $rc_type == RC_NEW ) {
2067 $r .= $N ;
2068 } else {
2069 $r .= '&nbsp;' ;
2070 }
2071 if ( $rc_minor ) {
2072 $r .= $M ;
2073 } else {
2074 $r .= '&nbsp;' ;
2075 }
2076 }
2077
2078 # Timestamp
2079 $r .= ' '.$rcObj->timestamp.' ' ;
2080 $r .= '</tt>' ;
2081
2082 # Article link
2083 $link = $rcObj->link ;
2084 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2085 $r .= $link ;
2086
2087 # Diff
2088 $r .= ' (' ;
2089 $r .= $rcObj->difflink ;
2090 $r .= '; ' ;
2091
2092 # Hist
2093 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2094
2095 # User/talk
2096 $r .= ') . . '.$rcObj->userlink ;
2097 $r .= $rcObj->usertalklink ;
2098
2099 # Comment
2100 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2101 $rc_comment=$this->formatComment($rc_comment);
2102 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2103 }
2104
2105 $r .= "<br />\n" ;
2106 return $r ;
2107 }
2108
2109 # Enhanced RC group
2110 function recentChangesBlockGroup ( $block )
2111 {
2112 global $wgStylePath, $wgLang ;
2113
2114 $r = '' ;
2115 $M = wfMsg( 'minoreditletter' );
2116 $N = wfMsg( 'newpageletter' );
2117
2118 # Collate list of users
2119 $isnew = false ;
2120 $userlinks = array () ;
2121 foreach ( $block AS $rcObj ) {
2122 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2123 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2124 $u = $rcObj->userlink ;
2125 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2126 $userlinks[$u]++ ;
2127 }
2128
2129 # Sort the list and convert to text
2130 krsort ( $userlinks ) ;
2131 asort ( $userlinks ) ;
2132 $users = array () ;
2133 foreach ( $userlinks as $userlink => $count) {
2134 $text = $userlink ;
2135 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2136 array_push ( $users , $text ) ;
2137 }
2138 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2139
2140 # Arrow
2141 $rci = 'RCI'.$this->rcCacheIndex ;
2142 $rcl = 'RCL'.$this->rcCacheIndex ;
2143 $rcm = 'RCM'.$this->rcCacheIndex ;
2144 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2145 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2146 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2147 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2148 $r .= $tl ;
2149
2150 # Main line
2151 # M/N
2152 $r .= '<tt>' ;
2153 if ( $isnew ) $r .= $N ;
2154 else $r .= '&nbsp;' ;
2155 $r .= '&nbsp;' ; # Minor
2156
2157 # Timestamp
2158 $r .= ' '.$block[0]->timestamp.' ' ;
2159 $r .= '</tt>' ;
2160
2161 # Article link
2162 $link = $block[0]->link ;
2163 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2164 $r .= $link ;
2165
2166 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2167 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2168 # Changes
2169 $r .= ' ('.count($block).' ' ;
2170 if ( $isnew ) $r .= wfMsg('changes');
2171 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2172 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2173 $r .= '; ' ;
2174
2175 # History
2176 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2177 $r .= ')' ;
2178 }
2179
2180 $r .= $users ;
2181 $r .= "<br />\n" ;
2182
2183 # Sub-entries
2184 $r .= '<div id="'.$rci.'" style="display:none">' ;
2185 foreach ( $block AS $rcObj ) {
2186 # Get rc_xxxx variables
2187 extract( $rcObj->mAttribs );
2188
2189 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2190 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2191 if ( $rc_new ) $r .= $N ;
2192 else $r .= '&nbsp;' ;
2193 if ( $rc_minor ) $r .= $M ;
2194 else $r .= '&nbsp;' ;
2195 $r .= '</tt>' ;
2196
2197 $o = '' ;
2198 if ( $rc_last_oldid != 0 ) {
2199 $o = 'oldid='.$rc_last_oldid ;
2200 }
2201 if ( $rc_type == RC_LOG ) {
2202 $link = $rcObj->timestamp ;
2203 } else {
2204 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2205 }
2206 $link = '<tt>'.$link.'</tt>' ;
2207
2208 $r .= $link ;
2209 $r .= ' (' ;
2210 $r .= $rcObj->curlink ;
2211 $r .= '; ' ;
2212 $r .= $rcObj->lastlink ;
2213 $r .= ') . . '.$rcObj->userlink ;
2214 $r .= $rcObj->usertalklink ;
2215 if ( $rc_comment != '' ) {
2216 $rc_comment=$this->formatComment($rc_comment);
2217 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2218 }
2219 $r .= "<br />\n" ;
2220 }
2221 $r .= "</div>\n" ;
2222
2223 $this->rcCacheIndex++ ;
2224 return $r ;
2225 }
2226
2227 # If enhanced RC is in use, this function takes the previously cached
2228 # RC lines, arranges them, and outputs the HTML
2229 function recentChangesBlock ()
2230 {
2231 global $wgStylePath ;
2232 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2233 $blockOut = '';
2234 foreach ( $this->rc_cache AS $secureName => $block ) {
2235 if ( count ( $block ) < 2 ) {
2236 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2237 } else {
2238 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2239 }
2240 }
2241
2242 return '<div>'.$blockOut.'</div>' ;
2243 }
2244
2245 # Called in a loop over all displayed RC entries
2246 # Either returns the line, or caches it for later use
2247 function recentChangesLine( &$rc, $watched = false )
2248 {
2249 global $wgUser ;
2250 $usenew = $wgUser->getOption( 'usenewrc' );
2251 if ( $usenew )
2252 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2253 else
2254 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2255 return $line ;
2256 }
2257
2258 function recentChangesLineOld( &$rc, $watched = false )
2259 {
2260 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2261
2262 # Extract DB fields into local scope
2263 extract( $rc->mAttribs );
2264 $curIdEq = 'curid=' . $rc_cur_id;
2265
2266 # Make date header if necessary
2267 $date = $wgLang->date( $rc_timestamp, true);
2268 $s = '';
2269 if ( $date != $this->lastdate ) {
2270 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2271 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2272 $this->lastdate = $date;
2273 $this->rclistOpen = true;
2274 }
2275
2276 # If this edit has not yet been patrolled, make it stick out
2277 $s .= ( ! $wgUseRCPatrol || $rc_patrolled ) ? '<li> ' : '<li class="not_patrolled"> ';
2278
2279 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2280 # Diff
2281 $s .= '(' . wfMsg( 'diff' ) . ') (';
2282 # Hist
2283 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2284 ') . . ';
2285
2286 # "[[x]] moved to [[y]]"
2287 $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
2288 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2289 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2290 } else {
2291 # Diff link
2292 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2293 $diffLink = wfMsg( 'diff' );
2294 } else {
2295 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2296 ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2297 $rcidparam = "&rcid={$rc_id}";
2298 else
2299 $rcidparam = "";
2300 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2301 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2302 '', '', ' tabindex="'.$rc->counter.'"');
2303 }
2304 $s .= '('.$diffLink.') (';
2305
2306 # History link
2307 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2308 $s .= ') . . ';
2309
2310 # M and N (minor and new)
2311 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2312 if ( $rc_type == RC_NEW ) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2313
2314 # Article link
2315 # If it's a new article, there is no diff link, but if it hasn't been
2316 # patrolled yet, we need to give users a way to do so
2317 if ( $wgUseRCPatrol && $rc_type == RC_NEW && $rc_patrolled == 0 &&
2318 $wgUser->getID() != 0 && ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2319 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2320 else
2321 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2322
2323 if ( $watched ) {
2324 $articleLink = '<strong>'.$articleLink.'</strong>';
2325 }
2326 $s .= ' '.$articleLink;
2327
2328 }
2329
2330 # Timestamp
2331 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2332
2333 # User link (or contributions for unregistered users)
2334 if ( 0 == $rc_user ) {
2335 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2336 $rc_user_text, 'target=' . $rc_user_text );
2337 } else {
2338 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2339 }
2340 $s .= $userLink;
2341
2342 # User talk link
2343 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2344 global $wgDisableAnonTalk;
2345 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2346 $userTalkLink = '';
2347 } else {
2348 $utns=$wgLang->getNsText(NS_USER_TALK);
2349 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2350 }
2351 # Block link
2352 $blockLink='';
2353 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2354 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2355 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2356
2357 }
2358 if($blockLink) {
2359 if($userTalkLink) $userTalkLink .= ' | ';
2360 $userTalkLink .= $blockLink;
2361 }
2362 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2363
2364 # Add comment
2365 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2366 $rc_comment=$this->formatComment($rc_comment);
2367 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2368 }
2369 $s .= "</li>\n";
2370
2371 return $s;
2372 }
2373
2374 function recentChangesLineNew( &$baseRC, $watched = false )
2375 {
2376 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2377
2378 # Create a specialised object
2379 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2380
2381 # Extract fields from DB into the function scope (rc_xxxx variables)
2382 extract( $rc->mAttribs );
2383 $curIdEq = 'curid=' . $rc_cur_id;
2384
2385 # If it's a new day, add the headline and flush the cache
2386 $date = $wgLang->date( $rc_timestamp, true);
2387 $ret = '';
2388 if ( $date != $this->lastdate ) {
2389 # Process current cache
2390 $ret = $this->recentChangesBlock () ;
2391 $this->rc_cache = array() ;
2392 $ret .= "<h4>{$date}</h4>\n";
2393 $this->lastdate = $date;
2394 }
2395
2396 # Make article link
2397 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2398 $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
2399 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2400 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2401 } else {
2402 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2403 }
2404
2405 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2406 $rc->watched = $watched ;
2407 $rc->link = $clink ;
2408 $rc->timestamp = $time;
2409
2410 # Make "cur" and "diff" links
2411 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2412 $curLink = wfMsg( 'cur' );
2413 $diffLink = wfMsg( 'diff' );
2414 } else {
2415 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2416 $aprops = ' tabindex="'.$baseRC->counter.'"';
2417 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2418 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2419 }
2420
2421 # Make "last" link
2422 $titleObj = $rc->getTitle();
2423 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2424 $lastLink = wfMsg( 'last' );
2425 } else {
2426 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2427 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2428 }
2429
2430 # Make user link (or user contributions for unregistered users)
2431 if ( $rc_user == 0 ) {
2432 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2433 $rc_user_text, 'target=' . $rc_user_text );
2434 } else {
2435 $userLink = $this->makeLink( $wgLang->getNsText(
2436 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2437 }
2438
2439 $rc->userlink = $userLink;
2440 $rc->lastlink = $lastLink;
2441 $rc->curlink = $curLink;
2442 $rc->difflink = $diffLink;
2443
2444 # Make user talk link
2445 $utns=$wgLang->getNsText(NS_USER_TALK);
2446 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2447 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2448
2449 global $wgDisableAnonTalk;
2450 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2451 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2452 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2453 if( $wgDisableAnonTalk )
2454 $rc->usertalklink = ' ('.$blockLink.')';
2455 else
2456 $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
2457 } else {
2458 if( $wgDisableAnonTalk && ($rc_user == 0) )
2459 $rc->usertalklink = '';
2460 else
2461 $rc->usertalklink = ' ('.$userTalkLink.')';
2462 }
2463
2464 # Put accumulated information into the cache, for later display
2465 # Page moves go on their own line
2466 $title = $rc->getTitle();
2467 $secureName = $title->getPrefixedDBkey();
2468 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2469 # Use an @ character to prevent collision with page names
2470 $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
2471 } else {
2472 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2473 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2474 }
2475 return $ret;
2476 }
2477
2478 function endImageHistoryList()
2479 {
2480 $s = "</ul>\n";
2481 return $s;
2482 }
2483
2484 /* This function is called by all recent changes variants, by the page history,
2485 and by the user contributions list. It is responsible for formatting edit
2486 comments. It escapes any HTML in the comment, but adds some CSS to format
2487 auto-generated comments (from section editing) and formats [[wikilinks]].
2488 Main author: Erik Möller (moeller@scireview.de)
2489 */
2490 function formatComment($comment)
2491 {
2492 global $wgLang;
2493 $comment=wfEscapeHTML($comment);
2494
2495 # The pattern for autogen comments is / * foo * /, which makes for
2496 # some nasty regex.
2497 # We look for all comments, match any text before and after the comment,
2498 # add a separator where needed and format the comment itself with CSS
2499 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2500 $pre=$match[1];
2501 $auto=$match[2];
2502 $post=$match[3];
2503 $sep='-';
2504 if($pre) { $auto = $sep.' '.$auto; }
2505 if($post) { $auto .= ' '.$sep; }
2506 $auto='<span class="autocomment">'.$auto.'</span>';
2507 $comment=$pre.$auto.$post;
2508 }
2509
2510 # format regular and media links - all other wiki formatting
2511 # is ignored
2512 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2513 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2514 # Handle link renaming [[foo|text]] will show link as "text"
2515 if( "" != $match[3] ) {
2516 $text = $match[3];
2517 } else {
2518 $text = $match[1];
2519 }
2520 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2521 # Media link; trail not supported.
2522 $linkRegexp = '/\[\[(.*?)\]\]/';
2523 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2524 } else {
2525 # Other kind of link
2526 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2527 $trail = $submatch[1];
2528 } else {
2529 $trail = "";
2530 }
2531 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2532 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2533 }
2534 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2535 }
2536 return $comment;
2537 }
2538
2539 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2540 {
2541 global $wgUser, $wgLang, $wgTitle;
2542
2543 $datetime = $wgLang->timeanddate( $timestamp, true );
2544 $del = wfMsg( 'deleteimg' );
2545 $delall = wfMsg( 'deleteimgcompletely' );
2546 $cur = wfMsg( 'cur' );
2547
2548 if ( $iscur ) {
2549 $url = Image::wfImageUrl( $img );
2550 $rlink = $cur;
2551 if ( $wgUser->isSysop() ) {
2552 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2553 '&action=delete' );
2554 $style = $this->getInternalLinkAttributes( $link, $delall );
2555
2556 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2557 } else {
2558 $dlink = $del;
2559 }
2560 } else {
2561 $url = wfEscapeHTML( wfImageArchiveUrl( $img ) );
2562 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2563 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2564 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2565 urlencode( $img ) );
2566 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2567 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2568 } else {
2569 # Having live active links for non-logged in users
2570 # means that bots and spiders crawling our site can
2571 # inadvertently change content. Baaaad idea.
2572 $rlink = wfMsg( 'revertimg' );
2573 $dlink = $del;
2574 }
2575 }
2576 if ( 0 == $user ) {
2577 $userlink = $usertext;
2578 } else {
2579 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2580 ':'.$usertext, $usertext );
2581 }
2582 $nbytes = wfMsg( 'nbytes', $size );
2583 $style = $this->getInternalLinkAttributes( $url, $datetime );
2584
2585 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2586 . " . . {$userlink} ({$nbytes})";
2587
2588 if ( '' != $description && '*' != $description ) {
2589 $sk=$wgUser->getSkin();
2590 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description) . ')');
2591 }
2592 $s .= "</li>\n";
2593 return $s;
2594 }
2595
2596 function tocIndent($level) {
2597 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2598 }
2599
2600 function tocUnindent($level) {
2601 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2602 }
2603
2604 # parameter level defines if we are on an indentation level
2605 function tocLine( $anchor, $tocline, $level ) {
2606 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2607 if($level) {
2608 return $link."\n";
2609 } else {
2610 return '<div class="tocline">'.$link."</div>\n";
2611 }
2612
2613 }
2614
2615 function tocTable($toc) {
2616 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2617 # try min-width & co when somebody gets a chance
2618 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2619 return
2620 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2621 '<b>'.wfMsg('toc').'</b>' .
2622 $hideline .
2623 '</td></tr><tr id="tocinside"><td>'."\n".
2624 $toc."</td></tr></table>\n";
2625 }
2626
2627 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2628 function editSectionScript( $section, $head ) {
2629 global $wgTitle, $wgRequest;
2630 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2631 return $head;
2632 }
2633 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2634 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2635 }
2636
2637 function editSectionLink( $section ) {
2638 global $wgRequest;
2639 global $wgTitle, $wgUser, $wgLang;
2640
2641 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2642 # Section edit links would be out of sync on an old page.
2643 # But, if we're diffing to the current page, they'll be
2644 # correct.
2645 return '';
2646 }
2647
2648 $editurl = '&section='.$section;
2649 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2650
2651 if( $wgLang->isRTL() ) {
2652 $farside = 'left';
2653 $nearside = 'right';
2654 } else {
2655 $farside = 'right';
2656 $nearside = 'left';
2657 }
2658 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2659
2660 }
2661
2662 // This function is called by EditPage.php and shows a bulletin board style
2663 // toolbar for common editing functions. It can be disabled in the user preferences.
2664 // The necsesary JavaScript code can be found in style/wikibits.js.
2665 function getEditToolbar() {
2666 global $wgStylePath, $wgLang, $wgMimeType;
2667
2668 // toolarray an array of arrays which each include the filename of
2669 // the button image (without path), the opening tag, the closing tag,
2670 // and optionally a sample text that is inserted between the two when no
2671 // selection is highlighted.
2672 // The tip text is shown when the user moves the mouse over the button.
2673
2674 // Already here are accesskeys (key), which are not used yet until someone
2675 // can figure out a way to make them work in IE. However, we should make
2676 // sure these keys are not defined on the edit page.
2677 $toolarray=array(
2678 array( 'image'=>'button_bold.png',
2679 'open'=>"\'\'\'",
2680 'close'=>"\'\'\'",
2681 'sample'=>wfMsg('bold_sample'),
2682 'tip'=>wfMsg('bold_tip'),
2683 'key'=>'B'
2684 ),
2685 array( "image"=>"button_italic.png",
2686 "open"=>"\'\'",
2687 "close"=>"\'\'",
2688 "sample"=>wfMsg("italic_sample"),
2689 "tip"=>wfMsg("italic_tip"),
2690 "key"=>"I"
2691 ),
2692 array( "image"=>"button_link.png",
2693 "open"=>"[[",
2694 "close"=>"]]",
2695 "sample"=>wfMsg("link_sample"),
2696 "tip"=>wfMsg("link_tip"),
2697 "key"=>"L"
2698 ),
2699 array( "image"=>"button_extlink.png",
2700 "open"=>"[",
2701 "close"=>"]",
2702 "sample"=>wfMsg("extlink_sample"),
2703 "tip"=>wfMsg("extlink_tip"),
2704 "key"=>"X"
2705 ),
2706 array( "image"=>"button_headline.png",
2707 "open"=>"\\n== ",
2708 "close"=>" ==\\n",
2709 "sample"=>wfMsg("headline_sample"),
2710 "tip"=>wfMsg("headline_tip"),
2711 "key"=>"H"
2712 ),
2713 array( "image"=>"button_image.png",
2714 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2715 "close"=>"]]",
2716 "sample"=>wfMsg("image_sample"),
2717 "tip"=>wfMsg("image_tip"),
2718 "key"=>"D"
2719 ),
2720 array( "image"=>"button_media.png",
2721 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2722 "close"=>"]]",
2723 "sample"=>wfMsg("media_sample"),
2724 "tip"=>wfMsg("media_tip"),
2725 "key"=>"M"
2726 ),
2727 array( "image"=>"button_math.png",
2728 "open"=>"\\<math\\>",
2729 "close"=>"\\</math\\>",
2730 "sample"=>wfMsg("math_sample"),
2731 "tip"=>wfMsg("math_tip"),
2732 "key"=>"C"
2733 ),
2734 array( "image"=>"button_nowiki.png",
2735 "open"=>"\\<nowiki\\>",
2736 "close"=>"\\</nowiki\\>",
2737 "sample"=>wfMsg("nowiki_sample"),
2738 "tip"=>wfMsg("nowiki_tip"),
2739 "key"=>"N"
2740 ),
2741 array( "image"=>"button_sig.png",
2742 "open"=>"--~~~~",
2743 "close"=>"",
2744 "sample"=>"",
2745 "tip"=>wfMsg("sig_tip"),
2746 "key"=>"Y"
2747 ),
2748 array( "image"=>"button_hr.png",
2749 "open"=>"\\n----\\n",
2750 "close"=>"",
2751 "sample"=>"",
2752 "tip"=>wfMsg("hr_tip"),
2753 "key"=>"R"
2754 )
2755 );
2756 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2757
2758 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2759 foreach($toolarray as $tool) {
2760
2761 $image=$wgStylePath.'/images/'.$tool['image'];
2762 $open=$tool['open'];
2763 $close=$tool['close'];
2764 $sample = addslashes( $tool['sample'] );
2765
2766 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2767 // Older browsers show a "speedtip" type message only for ALT.
2768 // Ideally these should be different, realistically they
2769 // probably don't need to be.
2770 $tip = addslashes( $tool['tip'] );
2771
2772 #$key = $tool["key"];
2773
2774 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2775 }
2776
2777 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2778 $toolbar.="document.writeln(\"</div>\");\n";
2779
2780 $toolbar.="/*]]>*/\n</script>";
2781 return $toolbar;
2782 }
2783
2784 }
2785
2786 }
2787 ?>