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