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