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