Show pretty localized log names in Recentchanges instead of Special:Log/upload etc
[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 # if ( '' != $section && substr($section,0,1) != "#" ) {
1576 # $section = ''
1577
1578 if ( '' == $link ) {
1579 $u = '';
1580 if ( '' == $text ) {
1581 $text = htmlspecialchars( $nt->getFragment() );
1582 }
1583 } else {
1584 $u = $nt->escapeLocalURL( $query );
1585 }
1586 if ( '' != $nt->getFragment() ) {
1587 $anchor = urlencode( do_html_entity_decode( str_replace(' ', '_', $nt->getFragment()), ENT_COMPAT, $wgInputEncoding ) );
1588 $replacearray = array(
1589 '%3A' => ':',
1590 '%' => '.'
1591 );
1592 $u .= '#' . str_replace(array_keys($replacearray),array_values($replacearray),$anchor);
1593 }
1594 if ( '' == $text ) {
1595 $text = htmlspecialchars( $nt->getPrefixedText() );
1596 }
1597 $style = $this->getInternalLinkAttributesObj( $nt, $text );
1598
1599 $inside = '';
1600 if ( '' != $trail ) {
1601 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1602 $inside = $m[1];
1603 $trail = $m[2];
1604 }
1605 }
1606 $r = "<a href=\"{$u}\"{$style}{$aprops}>{$prefix}{$text}{$inside}</a>{$trail}";
1607 wfProfileOut( $fname );
1608 return $r;
1609 }
1610
1611 # Pass a title object, not a title string
1612 function makeBrokenLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1613 {
1614 global $wgOut, $wgUser;
1615
1616 # Fail gracefully
1617 if ( ! isset($nt) )
1618 return "<!-- ERROR -->{$prefix}{$text}{$trail}";
1619
1620 $fname = 'Skin::makeBrokenLinkObj';
1621 wfProfileIn( $fname );
1622
1623 if ( '' == $query ) {
1624 $q = 'action=edit';
1625 } else {
1626 $q = 'action=edit&'.$query;
1627 }
1628 $u = $nt->escapeLocalURL( $q );
1629
1630 if ( '' == $text ) {
1631 $text = htmlspecialchars( $nt->getPrefixedText() );
1632 }
1633 $style = $this->getInternalLinkAttributesObj( $nt, $text, "yes" );
1634
1635 $inside = '';
1636 if ( '' != $trail ) {
1637 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1638 $inside = $m[1];
1639 $trail = $m[2];
1640 }
1641 }
1642 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1643 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1644 } else {
1645 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>?</a>{$trail}";
1646 }
1647
1648 wfProfileOut( $fname );
1649 return $s;
1650 }
1651
1652 # Pass a title object, not a title string
1653 function makeStubLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1654 {
1655 global $wgOut, $wgUser;
1656
1657 $link = $nt->getPrefixedURL();
1658
1659 $u = $nt->escapeLocalURL( $query );
1660
1661 if ( '' == $text ) {
1662 $text = htmlspecialchars( $nt->getPrefixedText() );
1663 }
1664 $style = $this->getInternalLinkAttributesObj( $nt, $text, 'stub' );
1665
1666 $inside = '';
1667 if ( '' != $trail ) {
1668 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1669 $inside = $m[1];
1670 $trail = $m[2];
1671 }
1672 }
1673 if ( $wgUser->getOption( 'highlightbroken' ) ) {
1674 $s = "<a href=\"{$u}\"{$style}>{$prefix}{$text}{$inside}</a>{$trail}";
1675 } else {
1676 $s = "{$prefix}{$text}{$inside}<a href=\"{$u}\"{$style}>!</a>{$trail}";
1677 }
1678 return $s;
1679 }
1680
1681 function makeSelfLinkObj( &$nt, $text = '', $query = '', $trail = '', $prefix = '' )
1682 {
1683 $u = $nt->escapeLocalURL( $query );
1684 if ( '' == $text ) {
1685 $text = htmlspecialchars( $nt->getPrefixedText() );
1686 }
1687 $inside = '';
1688 if ( '' != $trail ) {
1689 if ( preg_match( $this->linktrail, $trail, $m ) ) {
1690 $inside = $m[1];
1691 $trail = $m[2];
1692 }
1693 }
1694 return "<strong>{$prefix}{$text}{$inside}</strong>{$trail}";
1695 }
1696
1697 /* these are used extensively in SkinPHPTal, but also some other places */
1698 /*static*/ function makeSpecialUrl( $name, $urlaction='' ) {
1699 $title = Title::makeTitle( NS_SPECIAL, $name );
1700 $this->checkTitle($title, $name);
1701 return $title->getLocalURL( $urlaction );
1702 }
1703 /*static*/ function makeTalkUrl ( $name, $urlaction='' ) {
1704 $title = Title::newFromText( $name );
1705 $title = $title->getTalkPage();
1706 $this->checkTitle($title, $name);
1707 return $title->getLocalURL( $urlaction );
1708 }
1709 /*static*/ function makeArticleUrl ( $name, $urlaction='' ) {
1710 $title = Title::newFromText( $name );
1711 $title= $title->getSubjectPage();
1712 $this->checkTitle($title, $name);
1713 return $title->getLocalURL( $urlaction );
1714 }
1715 /*static*/ function makeI18nUrl ( $name, $urlaction='' ) {
1716 $title = Title::newFromText( wfMsg($name) );
1717 $this->checkTitle($title, $name);
1718 return $title->getLocalURL( $urlaction );
1719 }
1720 /*static*/ function makeUrl ( $name, $urlaction='' ) {
1721 $title = Title::newFromText( $name );
1722 $this->checkTitle($title, $name);
1723 return $title->getLocalURL( $urlaction );
1724 }
1725 # this can be passed the NS number as defined in Language.php
1726 /*static*/ function makeNSUrl( $name, $urlaction='', $namespace=0 ) {
1727 $title = Title::makeTitleSafe( $namespace, $name );
1728 $this->checkTitle($title, $name);
1729 return $title->getLocalURL( $urlaction );
1730 }
1731
1732 /* these return an array with the 'href' and boolean 'exists' */
1733 /*static*/ function makeUrlDetails ( $name, $urlaction='' ) {
1734 $title = Title::newFromText( $name );
1735 $this->checkTitle($title, $name);
1736 return array(
1737 'href' => $title->getLocalURL( $urlaction ),
1738 'exists' => $title->getArticleID() != 0?true:false
1739 );
1740 }
1741 /*static*/ function makeTalkUrlDetails ( $name, $urlaction='' ) {
1742 $title = Title::newFromText( $name );
1743 $title = $title->getTalkPage();
1744 $this->checkTitle($title, $name);
1745 return array(
1746 'href' => $title->getLocalURL( $urlaction ),
1747 'exists' => $title->getArticleID() != 0?true:false
1748 );
1749 }
1750 /*static*/ function makeArticleUrlDetails ( $name, $urlaction='' ) {
1751 $title = Title::newFromText( $name );
1752 $title= $title->getSubjectPage();
1753 $this->checkTitle($title, $name);
1754 return array(
1755 'href' => $title->getLocalURL( $urlaction ),
1756 'exists' => $title->getArticleID() != 0?true:false
1757 );
1758 }
1759 /*static*/ function makeI18nUrlDetails ( $name, $urlaction='' ) {
1760 $title = Title::newFromText( wfMsg($name) );
1761 $this->checkTitle($title, $name);
1762 return array(
1763 'href' => $title->getLocalURL( $urlaction ),
1764 'exists' => $title->getArticleID() != 0?true:false
1765 );
1766 }
1767
1768 # make sure we have some title to operate on
1769 /*static*/ function checkTitle ( &$title, &$name ) {
1770 if(!is_object($title)) {
1771 $title = Title::newFromText( $name );
1772 if(!is_object($title)) {
1773 $title = Title::newFromText( '--error: link target missing--' );
1774 }
1775 }
1776 }
1777
1778 function fnamePart( $url )
1779 {
1780 $basename = strrchr( $url, '/' );
1781 if ( false === $basename ) {
1782 $basename = $url;
1783 } else {
1784 $basename = substr( $basename, 1 );
1785 }
1786 return htmlspecialchars( $basename );
1787 }
1788
1789 function makeImage( $url, $alt = '' )
1790 {
1791 global $wgOut;
1792
1793 if ( '' == $alt ) {
1794 $alt = $this->fnamePart( $url );
1795 }
1796 $s = '<img src="'.$url.'" alt="'.$alt.'" />';
1797 return $s;
1798 }
1799
1800 function makeImageLink( $name, $url, $alt = '' ) {
1801 $nt = Title::makeTitleSafe( NS_IMAGE, $name );
1802 return $this->makeImageLinkObj( $nt, $alt );
1803 }
1804
1805 function makeImageLinkObj( $nt, $alt = '' ) {
1806 global $wgLang, $wgUseImageResize;
1807 $img = Image::newFromTitle( $nt );
1808 $url = $img->getURL();
1809
1810 $align = '';
1811 $prefix = $postfix = '';
1812
1813 if ( $wgUseImageResize ) {
1814 # Check if the alt text is of the form "options|alt text"
1815 # Options are:
1816 # * thumbnail make a thumbnail with enlarge-icon and caption, alignment depends on lang
1817 # * left no resizing, just left align. label is used for alt= only
1818 # * right same, but right aligned
1819 # * none same, but not aligned
1820 # * ___px scale to ___ pixels width, no aligning. e.g. use in taxobox
1821 # * center center the image
1822 # * framed Keep original image size, no magnify-button.
1823
1824 $part = explode( '|', $alt);
1825
1826 $mwThumb =& MagicWord::get( MAG_IMG_THUMBNAIL );
1827 $mwLeft =& MagicWord::get( MAG_IMG_LEFT );
1828 $mwRight =& MagicWord::get( MAG_IMG_RIGHT );
1829 $mwNone =& MagicWord::get( MAG_IMG_NONE );
1830 $mwWidth =& MagicWord::get( MAG_IMG_WIDTH );
1831 $mwCenter =& MagicWord::get( MAG_IMG_CENTER );
1832 $mwFramed =& MagicWord::get( MAG_IMG_FRAMED );
1833 $alt = $part[count($part)-1];
1834
1835 $height = $framed = $thumb = false;
1836 $manual_thumb = "" ;
1837
1838 foreach( $part as $key => $val ) {
1839 $val_parts = explode ( "=" , $val , 2 ) ;
1840 $left_part = array_shift ( $val_parts ) ;
1841 if ( ! is_null( $mwThumb->matchVariableStartToEnd($val) ) ) {
1842 $thumb=true;
1843 } elseif ( count ( $val_parts ) == 1 && ! is_null( $mwThumb->matchVariableStartToEnd($left_part) ) ) {
1844 # use manually specified thumbnail
1845 $thumb=true;
1846 $manual_thumb = array_shift ( $val_parts ) ;
1847 } elseif ( ! is_null( $mwRight->matchVariableStartToEnd($val) ) ) {
1848 # remember to set an alignment, don't render immediately
1849 $align = 'right';
1850 } elseif ( ! is_null( $mwLeft->matchVariableStartToEnd($val) ) ) {
1851 # remember to set an alignment, don't render immediately
1852 $align = 'left';
1853 } elseif ( ! is_null( $mwCenter->matchVariableStartToEnd($val) ) ) {
1854 # remember to set an alignment, don't render immediately
1855 $align = 'center';
1856 } elseif ( ! is_null( $mwNone->matchVariableStartToEnd($val) ) ) {
1857 # remember to set an alignment, don't render immediately
1858 $align = 'none';
1859 } elseif ( ! is_null( $match = $mwWidth->matchVariableStartToEnd($val) ) ) {
1860 # $match is the image width in pixels
1861 if ( preg_match( '/^([0-9]*)x([0-9]*)$/', $match, $m ) ) {
1862 $width = intval( $m[1] );
1863 $height = intval( $m[2] );
1864 } else {
1865 $width = intval($match);
1866 }
1867 } elseif ( ! is_null( $mwFramed->matchVariableStartToEnd($val) ) ) {
1868 $framed=true;
1869 }
1870 }
1871 if ( 'center' == $align )
1872 {
1873 $prefix = '<span style="text-align: center">';
1874 $postfix = '</span>';
1875 $align = 'none';
1876 }
1877
1878 if ( $thumb || $framed ) {
1879
1880 # Create a thumbnail. Alignment depends on language
1881 # writing direction, # right aligned for left-to-right-
1882 # languages ("Western languages"), left-aligned
1883 # for right-to-left-languages ("Semitic languages")
1884 #
1885 # If thumbnail width has not been provided, it is set
1886 # here to 180 pixels
1887 if ( $align == '' ) {
1888 $align = $wgLang->isRTL() ? 'left' : 'right';
1889 }
1890 if ( ! isset($width) ) {
1891 $width = 180;
1892 }
1893 return $prefix.$this->makeThumbLinkObj( $img, $alt, $align, $width, $height, $framed, $manual_thumb ).$postfix;
1894
1895 } elseif ( isset($width) ) {
1896
1897 # Create a resized image, without the additional thumbnail
1898 # features
1899
1900 if ( ( ! $height === false )
1901 && ( $img->getHeight() * $width / $img->getWidth() > $height ) ) {
1902 print "height=$height<br>\nimg->getHeight() = ".$img->getHeight()."<br>\n";
1903 print 'rescaling by factor '. $height / $img->getHeight() . "<br>\n";
1904 $width = $img->getWidth() * $height / $img->getHeight();
1905 }
1906 if ( '' == $manual_thumb ) $url = $img->createThumb( $width );
1907 }
1908 } # endif $wgUseImageResize
1909
1910 if ( empty( $alt ) ) {
1911 $alt = preg_replace( '/\.(.+?)^/', '', $img->getName() );
1912 }
1913 $alt = htmlspecialchars( $alt );
1914
1915 $u = $nt->escapeLocalURL();
1916 if ( $url == '' )
1917 {
1918 $s = wfMsg( 'missingimage', $img->getName() );
1919 $s .= "<br>{$alt}<br>{$url}<br>\n";
1920 } else {
1921 $s = '<a href="'.$u.'" class="image" title="'.$alt.'">' .
1922 '<img src="'.$url.'" alt="'.$alt.'" /></a>';
1923 }
1924 if ( '' != $align ) {
1925 $s = "<div class=\"float{$align}\"><span>{$s}</span></div>";
1926 }
1927 return str_replace("\n", ' ',$prefix.$s.$postfix);
1928 }
1929
1930 # Make HTML for a thumbnail including image, border and caption
1931 # $img is an Image object
1932 function makeThumbLinkObj( $img, $label = '', $align = 'right', $boxwidth = 180, $boxheight=false, $framed=false , $manual_thumb = "" ) {
1933 global $wgStylePath, $wgLang;
1934 # $image = Title::makeTitleSafe( NS_IMAGE, $name );
1935 $url = $img->getURL();
1936
1937 #$label = htmlspecialchars( $label );
1938 $alt = preg_replace( '/<[^>]*>/', '', $label);
1939 $alt = htmlspecialchars( $alt );
1940
1941 $width = $height = 0;
1942 if ( $img->exists() )
1943 {
1944 $width = $img->getWidth();
1945 $height = $img->getHeight();
1946 }
1947 if ( 0 == $width || 0 == $height )
1948 {
1949 $width = $height = 200;
1950 }
1951 if ( $boxwidth == 0 )
1952 {
1953 $boxwidth = 200;
1954 }
1955 if ( $framed )
1956 {
1957 // Use image dimensions, don't scale
1958 $boxwidth = $width;
1959 $oboxwidth = $boxwidth + 2;
1960 $boxheight = $height;
1961 $thumbUrl = $url;
1962 } else {
1963 $h = intval( $height/($width/$boxwidth) );
1964 $oboxwidth = $boxwidth + 2;
1965 if ( ( ! $boxheight === false ) && ( $h > $boxheight ) )
1966 {
1967 $boxwidth *= $boxheight/$h;
1968 } else {
1969 $boxheight = $h;
1970 }
1971 if ( '' == $manual_thumb ) $thumbUrl = $img->createThumb( $boxwidth );
1972 }
1973
1974 if ( $manual_thumb != '' ) # Use manually specified thumbnail
1975 {
1976 $manual_title = Title::makeTitleSafe( NS_IMAGE, $manual_thumb ); #new Title ( $manual_thumb ) ;
1977 $manual_img = Image::newFromTitle( $manual_title );
1978 $thumbUrl = $manual_img->getURL();
1979 if ( $manual_img->exists() )
1980 {
1981 $width = $manual_img->getWidth();
1982 $height = $manual_img->getHeight();
1983 $boxwidth = $width ;
1984 $boxheight = $height ;
1985 $oboxwidth = $boxwidth + 2 ;
1986 }
1987 }
1988
1989 $u = $img->getEscapeLocalURL();
1990
1991 $more = htmlspecialchars( wfMsg( 'thumbnail-more' ) );
1992 $magnifyalign = $wgLang->isRTL() ? 'left' : 'right';
1993 $textalign = $wgLang->isRTL() ? ' style="text-align:right"' : '';
1994
1995 $s = "<div class=\"thumb t{$align}\"><div style=\"width:{$oboxwidth}px;\">";
1996 if ( $thumbUrl == '' ) {
1997 $s .= wfMsg( 'missingimage', $img->getName() );
1998 $zoomicon = '';
1999 } else {
2000 $s .= '<a href="'.$u.'" class="internal" title="'.$alt.'">'.
2001 '<img src="'.$thumbUrl.'" alt="'.$alt.'" ' .
2002 'width="'.$boxwidth.'" height="'.$boxheight.'" /></a>';
2003 if ( $framed ) {
2004 $zoomicon="";
2005 } else {
2006 $zoomicon = '<div class="magnify" style="float:'.$magnifyalign.'">'.
2007 '<a href="'.$u.'" class="internal" title="'.$more.'">'.
2008 '<img src="'.$wgStylePath.'/images/magnify-clip.png" ' .
2009 'width="15" height="11" alt="'.$more.'" /></a></div>';
2010 }
2011 }
2012 $s .= ' <div class="thumbcaption" '.$textalign.'>'.$zoomicon.$label."</div></div></div>";
2013 return str_replace("\n", ' ', $s);
2014 }
2015
2016 function makeMediaLink( $name, $url, $alt = "" ) {
2017 $nt = Title::makeTitleSafe( Namespace::getMedia(), $name );
2018 return $this->makeMediaLinkObj( $nt, $alt );
2019 }
2020
2021 function makeMediaLinkObj( $nt, $alt = "" )
2022 {
2023 if ( ! isset( $nt ) )
2024 {
2025 ### HOTFIX. Instead of breaking, return empty string.
2026 $s = $alt;
2027 } else {
2028 $name = $nt->getDBKey();
2029 $url = Image::wfImageUrl( $name );
2030 if ( empty( $alt ) ) {
2031 $alt = preg_replace( '/\.(.+?)^/', '', $name );
2032 }
2033
2034 $u = htmlspecialchars( $url );
2035 $s = "<a href=\"{$u}\" class='internal' title=\"{$alt}\">{$alt}</a>";
2036 }
2037 return $s;
2038 }
2039
2040 function specialLink( $name, $key = "" )
2041 {
2042 global $wgLang;
2043
2044 if ( '' == $key ) { $key = strtolower( $name ); }
2045 $pn = $wgLang->ucfirst( $name );
2046 return $this->makeKnownLink( $wgLang->specialPage( $pn ),
2047 wfMsg( $key ) );
2048 }
2049
2050 function makeExternalLink( $url, $text, $escape = true ) {
2051 $style = $this->getExternalLinkAttributes( $url, $text );
2052 $url = htmlspecialchars( $url );
2053 if( $escape ) {
2054 $text = htmlspecialchars( $text );
2055 }
2056 return '<a href="'.$url.'"'.$style.'>'.$text.'</a>';
2057 }
2058
2059 # Called by history lists and recent changes
2060 #
2061
2062 # Returns text for the start of the tabular part of RC
2063 function beginRecentChangesList()
2064 {
2065 $this->rc_cache = array() ;
2066 $this->rcMoveIndex = 0;
2067 $this->rcCacheIndex = 0 ;
2068 $this->lastdate = '';
2069 $this->rclistOpen = false;
2070 return '';
2071 }
2072
2073 function beginImageHistoryList()
2074 {
2075 $s = "\n<h2>" . wfMsg( 'imghistory' ) . "</h2>\n" .
2076 "<p>" . wfMsg( 'imghistlegend' ) . "</p>\n".'<ul class="special">';
2077 return $s;
2078 }
2079
2080 # Returns text for the end of RC
2081 # If enhanced RC is in use, returns pretty much all the text
2082 function endRecentChangesList()
2083 {
2084 $s = $this->recentChangesBlock() ;
2085 if( $this->rclistOpen ) {
2086 $s .= "</ul>\n";
2087 }
2088 return $s;
2089 }
2090
2091 # Enhanced RC ungrouped line
2092 function recentChangesBlockLine ( $rcObj )
2093 {
2094 global $wgStylePath, $wgLang ;
2095
2096 # Get rc_xxxx variables
2097 extract( $rcObj->mAttribs ) ;
2098 $curIdEq = 'curid='.$rc_cur_id;
2099
2100 # Spacer image
2101 $r = '' ;
2102
2103 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" border="0" />' ;
2104 $r .= '<tt>' ;
2105
2106 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2107 $r .= '&nbsp;&nbsp;';
2108 } else {
2109 # M & N (minor & new)
2110 $M = wfMsg( 'minoreditletter' );
2111 $N = wfMsg( 'newpageletter' );
2112
2113 if ( $rc_type == RC_NEW ) {
2114 $r .= $N ;
2115 } else {
2116 $r .= '&nbsp;' ;
2117 }
2118 if ( $rc_minor ) {
2119 $r .= $M ;
2120 } else {
2121 $r .= '&nbsp;' ;
2122 }
2123 }
2124
2125 # Timestamp
2126 $r .= ' '.$rcObj->timestamp.' ' ;
2127 $r .= '</tt>' ;
2128
2129 # Article link
2130 $link = $rcObj->link ;
2131 if ( $rcObj->watched ) $link = '<strong>'.$link.'</strong>' ;
2132 $r .= $link ;
2133
2134 # Diff
2135 $r .= ' (' ;
2136 $r .= $rcObj->difflink ;
2137 $r .= '; ' ;
2138
2139 # Hist
2140 $r .= $this->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2141
2142 # User/talk
2143 $r .= ') . . '.$rcObj->userlink ;
2144 $r .= $rcObj->usertalklink ;
2145
2146 # Comment
2147 if ( $rc_comment != '' && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2148 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2149 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' );
2150 }
2151
2152 $r .= "<br />\n" ;
2153 return $r ;
2154 }
2155
2156 # Enhanced RC group
2157 function recentChangesBlockGroup ( $block )
2158 {
2159 global $wgStylePath, $wgLang ;
2160
2161 $r = '' ;
2162 $M = wfMsg( 'minoreditletter' );
2163 $N = wfMsg( 'newpageletter' );
2164
2165 # Collate list of users
2166 $isnew = false ;
2167 $userlinks = array () ;
2168 foreach ( $block AS $rcObj ) {
2169 $oldid = $rcObj->mAttribs['rc_last_oldid'];
2170 if ( $rcObj->mAttribs['rc_new'] ) $isnew = true ;
2171 $u = $rcObj->userlink ;
2172 if ( !isset ( $userlinks[$u] ) ) $userlinks[$u] = 0 ;
2173 $userlinks[$u]++ ;
2174 }
2175
2176 # Sort the list and convert to text
2177 krsort ( $userlinks ) ;
2178 asort ( $userlinks ) ;
2179 $users = array () ;
2180 foreach ( $userlinks as $userlink => $count) {
2181 $text = $userlink ;
2182 if ( $count > 1 ) $text .= " ({$count}&times;)" ;
2183 array_push ( $users , $text ) ;
2184 }
2185 $users = ' <font size="-1">['.implode('; ',$users).']</font>' ;
2186
2187 # Arrow
2188 $rci = 'RCI'.$this->rcCacheIndex ;
2189 $rcl = 'RCL'.$this->rcCacheIndex ;
2190 $rcm = 'RCM'.$this->rcCacheIndex ;
2191 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')" ;
2192 $arrowdir = $wgLang->isRTL() ? 'l' : 'r';
2193 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_'.$arrowdir.'.png" width="12" height="12" /></a></span>' ;
2194 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'"><img src="'.$wgStylePath.'/images/Arr_d.png" width="12" height="12" /></a></span>' ;
2195 $r .= $tl ;
2196
2197 # Main line
2198 # M/N
2199 $r .= '<tt>' ;
2200 if ( $isnew ) $r .= $N ;
2201 else $r .= '&nbsp;' ;
2202 $r .= '&nbsp;' ; # Minor
2203
2204 # Timestamp
2205 $r .= ' '.$block[0]->timestamp.' ' ;
2206 $r .= '</tt>' ;
2207
2208 # Article link
2209 $link = $block[0]->link ;
2210 if ( $block[0]->watched ) $link = '<strong>'.$link.'</strong>' ;
2211 $r .= $link ;
2212
2213 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
2214 if ( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
2215 # Changes
2216 $r .= ' ('.count($block).' ' ;
2217 if ( $isnew ) $r .= wfMsg('changes');
2218 else $r .= $this->makeKnownLinkObj( $block[0]->getTitle() , wfMsg('changes') ,
2219 $curIdEq.'&diff=0&oldid='.$oldid ) ;
2220 $r .= '; ' ;
2221
2222 # History
2223 $r .= $this->makeKnownLinkObj( $block[0]->getTitle(), wfMsg( 'history' ), $curIdEq.'&action=history' );
2224 $r .= ')' ;
2225 }
2226
2227 $r .= $users ;
2228 $r .= "<br />\n" ;
2229
2230 # Sub-entries
2231 $r .= '<div id="'.$rci.'" style="display:none">' ;
2232 foreach ( $block AS $rcObj ) {
2233 # Get rc_xxxx variables
2234 extract( $rcObj->mAttribs );
2235
2236 $r .= '<img src="'.$wgStylePath.'/images/Arr_.png" width="12" height="12" />';
2237 $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;' ;
2238 if ( $rc_new ) $r .= $N ;
2239 else $r .= '&nbsp;' ;
2240 if ( $rc_minor ) $r .= $M ;
2241 else $r .= '&nbsp;' ;
2242 $r .= '</tt>' ;
2243
2244 $o = '' ;
2245 if ( $rc_last_oldid != 0 ) {
2246 $o = 'oldid='.$rc_last_oldid ;
2247 }
2248 if ( $rc_type == RC_LOG ) {
2249 $link = $rcObj->timestamp ;
2250 } else {
2251 $link = $this->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp , "{$curIdEq}&$o" ) ;
2252 }
2253 $link = '<tt>'.$link.'</tt>' ;
2254
2255 $r .= $link ;
2256 $r .= ' (' ;
2257 $r .= $rcObj->curlink ;
2258 $r .= '; ' ;
2259 $r .= $rcObj->lastlink ;
2260 $r .= ') . . '.$rcObj->userlink ;
2261 $r .= $rcObj->usertalklink ;
2262 if ( $rc_comment != '' ) {
2263 $rc_comment=$this->formatComment($rc_comment, $rcObj->getTitle());
2264 $r .= $wgLang->emphasize( ' ('.$rc_comment.')' ) ;
2265 }
2266 $r .= "<br />\n" ;
2267 }
2268 $r .= "</div>\n" ;
2269
2270 $this->rcCacheIndex++ ;
2271 return $r ;
2272 }
2273
2274 # If enhanced RC is in use, this function takes the previously cached
2275 # RC lines, arranges them, and outputs the HTML
2276 function recentChangesBlock ()
2277 {
2278 global $wgStylePath ;
2279 if ( count ( $this->rc_cache ) == 0 ) return '' ;
2280 $blockOut = '';
2281 foreach ( $this->rc_cache AS $secureName => $block ) {
2282 if ( count ( $block ) < 2 ) {
2283 $blockOut .= $this->recentChangesBlockLine ( array_shift ( $block ) ) ;
2284 } else {
2285 $blockOut .= $this->recentChangesBlockGroup ( $block ) ;
2286 }
2287 }
2288
2289 return '<div>'.$blockOut.'</div>' ;
2290 }
2291
2292 # Called in a loop over all displayed RC entries
2293 # Either returns the line, or caches it for later use
2294 function recentChangesLine( &$rc, $watched = false )
2295 {
2296 global $wgUser ;
2297 $usenew = $wgUser->getOption( 'usenewrc' );
2298 if ( $usenew )
2299 $line = $this->recentChangesLineNew ( $rc, $watched ) ;
2300 else
2301 $line = $this->recentChangesLineOld ( $rc, $watched ) ;
2302 return $line ;
2303 }
2304
2305 function recentChangesLineOld( &$rc, $watched = false )
2306 {
2307 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds, $wgUseRCPatrol, $wgOnlySysopsCanPatrol;
2308
2309 # Extract DB fields into local scope
2310 extract( $rc->mAttribs );
2311 $curIdEq = 'curid=' . $rc_cur_id;
2312
2313 # Make date header if necessary
2314 $date = $wgLang->date( $rc_timestamp, true);
2315 $s = '';
2316 if ( $date != $this->lastdate ) {
2317 if ( '' != $this->lastdate ) { $s .= "</ul>\n"; }
2318 $s .= "<h4>{$date}</h4>\n<ul class='special'>";
2319 $this->lastdate = $date;
2320 $this->rclistOpen = true;
2321 }
2322
2323 # If this edit has not yet been patrolled, make it stick out
2324 $s .= ( ! $wgUseRCPatrol || $rc_patrolled ) ? '<li> ' : '<li class="not_patrolled"> ';
2325
2326 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2327 # Diff
2328 $s .= '(' . wfMsg( 'diff' ) . ') (';
2329 # Hist
2330 $s .= $this->makeKnownLinkObj( $rc->getMovedToTitle(), wfMsg( 'hist' ), 'action=history' ) .
2331 ') . . ';
2332
2333 # "[[x]] moved to [[y]]"
2334 $msg = ( $rc_type == RC_MOVE ) ? '1movedto2' : '1movedto2_redir';
2335 $s .= wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2336 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2337 } elseif( $rc_namespace == NS_SPECIAL && preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2338 # Log updates, etc
2339 $logtype = $matches[1];
2340 $logname = LogPage::logName( $logtype );
2341 $s .= '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2342 } else {
2343 # Diff link
2344 if ( $rc_type == RC_NEW || $rc_type == RC_LOG ) {
2345 $diffLink = wfMsg( 'diff' );
2346 } else {
2347 if ( $wgUseRCPatrol && $rc_patrolled == 0 && $wgUser->getID() != 0 &&
2348 ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2349 $rcidparam = "&rcid={$rc_id}";
2350 else
2351 $rcidparam = "";
2352 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff' ),
2353 "{$curIdEq}&diff={$rc_this_oldid}&oldid={$rc_last_oldid}{$rcidparam}",
2354 '', '', ' tabindex="'.$rc->counter.'"');
2355 }
2356 $s .= '('.$diffLink.') (';
2357
2358 # History link
2359 $s .= $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' );
2360 $s .= ') . . ';
2361
2362 # M and N (minor and new)
2363 if ( $rc_minor ) { $s .= ' <span class="minor">'.wfMsg( "minoreditletter" ).'</span>'; }
2364 if ( $rc_type == RC_NEW ) { $s .= '<span class="newpage">'.wfMsg( "newpageletter" ).'</span>'; }
2365
2366 # Article link
2367 # If it's a new article, there is no diff link, but if it hasn't been
2368 # patrolled yet, we need to give users a way to do so
2369 if ( $wgUseRCPatrol && $rc_type == RC_NEW && $rc_patrolled == 0 &&
2370 $wgUser->getID() != 0 && ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
2371 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
2372 else
2373 $articleLink = $this->makeKnownLinkObj( $rc->getTitle(), '' );
2374
2375 if ( $watched ) {
2376 $articleLink = '<strong>'.$articleLink.'</strong>';
2377 }
2378 $s .= ' '.$articleLink;
2379
2380 }
2381
2382 # Timestamp
2383 $s .= '; ' . $wgLang->time( $rc_timestamp, true, $wgRCSeconds ) . ' . . ';
2384
2385 # User link (or contributions for unregistered users)
2386 if ( 0 == $rc_user ) {
2387 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2388 $rc_user_text, 'target=' . $rc_user_text );
2389 } else {
2390 $userLink = $this->makeLink( $wgLang->getNsText( NS_USER ) . ':'.$rc_user_text, $rc_user_text );
2391 }
2392 $s .= $userLink;
2393
2394 # User talk link
2395 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2396 global $wgDisableAnonTalk;
2397 if( 0 == $rc_user && $wgDisableAnonTalk ) {
2398 $userTalkLink = '';
2399 } else {
2400 $utns=$wgLang->getNsText(NS_USER_TALK);
2401 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2402 }
2403 # Block link
2404 $blockLink='';
2405 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2406 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2407 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2408
2409 }
2410 if($blockLink) {
2411 if($userTalkLink) $userTalkLink .= ' | ';
2412 $userTalkLink .= $blockLink;
2413 }
2414 if($userTalkLink) $s.=' ('.$userTalkLink.')';
2415
2416 # Add comment
2417 if ( '' != $rc_comment && '*' != $rc_comment && $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
2418 $rc_comment=$this->formatComment($rc_comment,$rc->getTitle());
2419 $s .= $wgLang->emphasize(' (' . $rc_comment . ')');
2420 }
2421 $s .= "</li>\n";
2422
2423 return $s;
2424 }
2425
2426 function recentChangesLineNew( &$baseRC, $watched = false )
2427 {
2428 global $wgTitle, $wgLang, $wgUser, $wgRCSeconds;
2429
2430 # Create a specialised object
2431 $rc = RCCacheEntry::newFromParent( $baseRC ) ;
2432
2433 # Extract fields from DB into the function scope (rc_xxxx variables)
2434 extract( $rc->mAttribs );
2435 $curIdEq = 'curid=' . $rc_cur_id;
2436
2437 # If it's a new day, add the headline and flush the cache
2438 $date = $wgLang->date( $rc_timestamp, true);
2439 $ret = '';
2440 if ( $date != $this->lastdate ) {
2441 # Process current cache
2442 $ret = $this->recentChangesBlock () ;
2443 $this->rc_cache = array() ;
2444 $ret .= "<h4>{$date}</h4>\n";
2445 $this->lastdate = $date;
2446 }
2447
2448 # Make article link
2449 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2450 $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
2451 $clink = wfMsg( $msg, $this->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
2452 $this->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
2453 } elseif( $rc_namespace == NS_SPECIAL && preg_match( '!^Log/(.*)$!', $rc_title, $matches ) ) {
2454 # Log updates, etc
2455 $logtype = $matches[1];
2456 $logname = LogPage::logName( $logtype );
2457 $clink = '(' . $this->makeKnownLinkObj( $rc->getTitle(), $logname ) . ')';
2458 } else {
2459 $clink = $this->makeKnownLinkObj( $rc->getTitle(), '' ) ;
2460 }
2461
2462 $time = $wgLang->time( $rc_timestamp, true, $wgRCSeconds );
2463 $rc->watched = $watched ;
2464 $rc->link = $clink ;
2465 $rc->timestamp = $time;
2466
2467 # Make "cur" and "diff" links
2468 if ( ( $rc_type == RC_NEW && $rc_this_oldid == 0 ) || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2469 $curLink = wfMsg( 'cur' );
2470 $diffLink = wfMsg( 'diff' );
2471 } else {
2472 $query = $curIdEq.'&diff=0&oldid='.$rc_this_oldid;
2473 $aprops = ' tabindex="'.$baseRC->counter.'"';
2474 $curLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'cur' ), $query, '' ,'' , $aprops );
2475 $diffLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'diff'), $query, '' ,'' , $aprops );
2476 }
2477
2478 # Make "last" link
2479 $titleObj = $rc->getTitle();
2480 if ( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2481 $lastLink = wfMsg( 'last' );
2482 } else {
2483 $lastLink = $this->makeKnownLinkObj( $rc->getTitle(), wfMsg( 'last' ),
2484 $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid );
2485 }
2486
2487 # Make user link (or user contributions for unregistered users)
2488 if ( $rc_user == 0 ) {
2489 $userLink = $this->makeKnownLink( $wgLang->specialPage( 'Contributions' ),
2490 $rc_user_text, 'target=' . $rc_user_text );
2491 } else {
2492 $userLink = $this->makeLink( $wgLang->getNsText(
2493 Namespace::getUser() ) . ':'.$rc_user_text, $rc_user_text );
2494 }
2495
2496 $rc->userlink = $userLink;
2497 $rc->lastlink = $lastLink;
2498 $rc->curlink = $curLink;
2499 $rc->difflink = $diffLink;
2500
2501 # Make user talk link
2502 $utns=$wgLang->getNsText(NS_USER_TALK);
2503 $talkname=$wgLang->getNsText(NS_TALK); # use the shorter name
2504 $userTalkLink= $this->makeLink($utns . ':'.$rc_user_text, $talkname );
2505
2506 global $wgDisableAnonTalk;
2507 if ( ( 0 == $rc_user ) && $wgUser->isSysop() ) {
2508 $blockLink = $this->makeKnownLink( $wgLang->specialPage(
2509 'Blockip' ), wfMsg( 'blocklink' ), 'ip='.$rc_user_text );
2510 if( $wgDisableAnonTalk )
2511 $rc->usertalklink = ' ('.$blockLink.')';
2512 else
2513 $rc->usertalklink = ' ('.$userTalkLink.' | '.$blockLink.')';
2514 } else {
2515 if( $wgDisableAnonTalk && ($rc_user == 0) )
2516 $rc->usertalklink = '';
2517 else
2518 $rc->usertalklink = ' ('.$userTalkLink.')';
2519 }
2520
2521 # Put accumulated information into the cache, for later display
2522 # Page moves go on their own line
2523 $title = $rc->getTitle();
2524 $secureName = $title->getPrefixedDBkey();
2525 if ( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
2526 # Use an @ character to prevent collision with page names
2527 $this->rc_cache['@@' . ($this->rcMoveIndex++)] = array($rc);
2528 } else {
2529 if ( !isset ( $this->rc_cache[$secureName] ) ) $this->rc_cache[$secureName] = array() ;
2530 array_push ( $this->rc_cache[$secureName] , $rc ) ;
2531 }
2532 return $ret;
2533 }
2534
2535 function endImageHistoryList()
2536 {
2537 $s = "</ul>\n";
2538 return $s;
2539 }
2540
2541 /* This function is called by all recent changes variants, by the page history,
2542 and by the user contributions list. It is responsible for formatting edit
2543 comments. It escapes any HTML in the comment, but adds some CSS to format
2544 auto-generated comments (from section editing) and formats [[wikilinks]].
2545
2546 The &$title parameter must be a title OBJECT. It is used to generate a
2547 direct link to the section in the autocomment.
2548 Main author: Erik Moeller (moeller@scireview.de)
2549 */
2550 # Note: there's not always a title to pass to this function.
2551 # Since you can't set a default parameter for a reference, I've turned it
2552 # temporarily to a value pass. Should be adjusted further. --brion
2553 function formatComment($comment, $title = NULL)
2554 {
2555 global $wgLang;
2556 $comment = htmlspecialchars( $comment );
2557
2558 # The pattern for autogen comments is / * foo * /, which makes for
2559 # some nasty regex.
2560 # We look for all comments, match any text before and after the comment,
2561 # add a separator where needed and format the comment itself with CSS
2562 while (preg_match('/(.*)\/\*\s*(.*?)\s*\*\/(.*)/', $comment,$match)) {
2563 $pre=$match[1];
2564 $auto=$match[2];
2565 $post=$match[3];
2566 $link='';
2567 if($title) {
2568 $section=$auto;
2569
2570 # This is hackish but should work in most cases.
2571 $section=str_replace('[[','',$section);
2572 $section=str_replace(']]','',$section);
2573 $title->mFragment=$section;
2574 $link=$this->makeKnownLinkObj($title,wfMsg('sectionlink'));
2575 }
2576 $sep='-';
2577 $auto=$link.$auto;
2578 if($pre) { $auto = $sep.' '.$auto; }
2579 if($post) { $auto .= ' '.$sep; }
2580 $auto='<span class="autocomment">'.$auto.'</span>';
2581 $comment=$pre.$auto.$post;
2582 }
2583
2584 # format regular and media links - all other wiki formatting
2585 # is ignored
2586 $medians = $wgLang->getNsText(Namespace::getMedia()).':';
2587 while(preg_match('/\[\[(.*?)(\|(.*?))*\]\](.*)$/',$comment,$match)) {
2588 # Handle link renaming [[foo|text]] will show link as "text"
2589 if( "" != $match[3] ) {
2590 $text = $match[3];
2591 } else {
2592 $text = $match[1];
2593 }
2594 if( preg_match( '/^' . $medians . '(.*)$/i', $match[1], $submatch ) ) {
2595 # Media link; trail not supported.
2596 $linkRegexp = '/\[\[(.*?)\]\]/';
2597 $thelink = $this->makeMediaLink( $submatch[1], "", $text );
2598 } else {
2599 # Other kind of link
2600 if( preg_match( wfMsg( "linktrail" ), $match[4], $submatch ) ) {
2601 $trail = $submatch[1];
2602 } else {
2603 $trail = "";
2604 }
2605 $linkRegexp = '/\[\[(.*?)\]\]' . preg_quote( $trail, '/' ) . '/';
2606 if ($match[1][0] == ':')
2607 $match[1] = substr($match[1], 1);
2608 $thelink = $this->makeLink( $match[1], $text, "", $trail );
2609 }
2610 $comment = preg_replace( $linkRegexp, $thelink, $comment, 1 );
2611 }
2612 return $comment;
2613 }
2614
2615 function imageHistoryLine( $iscur, $timestamp, $img, $user, $usertext, $size, $description )
2616 {
2617 global $wgUser, $wgLang, $wgTitle;
2618
2619 $datetime = $wgLang->timeanddate( $timestamp, true );
2620 $del = wfMsg( 'deleteimg' );
2621 $delall = wfMsg( 'deleteimgcompletely' );
2622 $cur = wfMsg( 'cur' );
2623
2624 if ( $iscur ) {
2625 $url = Image::wfImageUrl( $img );
2626 $rlink = $cur;
2627 if ( $wgUser->isSysop() ) {
2628 $link = $wgTitle->escapeLocalURL( 'image=' . $wgTitle->getPartialURL() .
2629 '&action=delete' );
2630 $style = $this->getInternalLinkAttributes( $link, $delall );
2631
2632 $dlink = '<a href="'.$link.'"'.$style.'>'.$delall.'</a>';
2633 } else {
2634 $dlink = $del;
2635 }
2636 } else {
2637 $url = htmlspecialchars( wfImageArchiveUrl( $img ) );
2638 if( $wgUser->getID() != 0 && $wgTitle->userCanEdit() ) {
2639 $rlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2640 wfMsg( 'revertimg' ), 'action=revert&oldimage=' .
2641 urlencode( $img ) );
2642 $dlink = $this->makeKnownLink( $wgTitle->getPrefixedText(),
2643 $del, 'action=delete&oldimage=' . urlencode( $img ) );
2644 } else {
2645 # Having live active links for non-logged in users
2646 # means that bots and spiders crawling our site can
2647 # inadvertently change content. Baaaad idea.
2648 $rlink = wfMsg( 'revertimg' );
2649 $dlink = $del;
2650 }
2651 }
2652 if ( 0 == $user ) {
2653 $userlink = $usertext;
2654 } else {
2655 $userlink = $this->makeLink( $wgLang->getNsText( Namespace::getUser() ) .
2656 ':'.$usertext, $usertext );
2657 }
2658 $nbytes = wfMsg( 'nbytes', $size );
2659 $style = $this->getInternalLinkAttributes( $url, $datetime );
2660
2661 $s = "<li> ({$dlink}) ({$rlink}) <a href=\"{$url}\"{$style}>{$datetime}</a>"
2662 . " . . {$userlink} ({$nbytes})";
2663
2664 if ( '' != $description && '*' != $description ) {
2665 $sk=$wgUser->getSkin();
2666 $s .= $wgLang->emphasize(' (' . $sk->formatComment($description,$wgTitle) . ')');
2667 }
2668 $s .= "</li>\n";
2669 return $s;
2670 }
2671
2672 function tocIndent($level) {
2673 return str_repeat( '<div class="tocindent">'."\n", $level>0 ? $level : 0 );
2674 }
2675
2676 function tocUnindent($level) {
2677 return str_repeat( "</div>\n", $level>0 ? $level : 0 );
2678 }
2679
2680 # parameter level defines if we are on an indentation level
2681 function tocLine( $anchor, $tocline, $level ) {
2682 $link = '<a href="#'.$anchor.'">'.$tocline.'</a><br />';
2683 if($level) {
2684 return $link."\n";
2685 } else {
2686 return '<div class="tocline">'.$link."</div>\n";
2687 }
2688
2689 }
2690
2691 function tocTable($toc) {
2692 # note to CSS fanatics: putting this in a div does not work -- div won't auto-expand
2693 # try min-width & co when somebody gets a chance
2694 $hideline = ' <script type="text/javascript">showTocToggle("' . addslashes( wfMsg('showtoc') ) . '","' . addslashes( wfMsg('hidetoc') ) . '")</script>';
2695 return
2696 '<table border="0" id="toc"><tr id="toctitle"><td align="center">'."\n".
2697 '<b>'.wfMsg('toc').'</b>' .
2698 $hideline .
2699 '</td></tr><tr id="tocinside"><td>'."\n".
2700 $toc."</td></tr></table>\n";
2701 }
2702
2703 # These two do not check for permissions: check $wgTitle->userCanEdit before calling them
2704 function editSectionScript( $section, $head ) {
2705 global $wgTitle, $wgRequest;
2706 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2707 return $head;
2708 }
2709 $url = $wgTitle->escapeLocalURL( 'action=edit&section='.$section );
2710 return '<span oncontextmenu=\'document.location="'.$url.'";return false;\'>'.$head.'</span>';
2711 }
2712
2713 function editSectionLink( $section ) {
2714 global $wgRequest;
2715 global $wgTitle, $wgUser, $wgLang;
2716
2717 if( $wgRequest->getInt( 'oldid' ) && ( $wgRequest->getVal( 'diff' ) != '0' ) ) {
2718 # Section edit links would be out of sync on an old page.
2719 # But, if we're diffing to the current page, they'll be
2720 # correct.
2721 return '';
2722 }
2723
2724 $editurl = '&section='.$section;
2725 $url = $this->makeKnownLink($wgTitle->getPrefixedText(),wfMsg('editsection'),'action=edit'.$editurl);
2726
2727 if( $wgLang->isRTL() ) {
2728 $farside = 'left';
2729 $nearside = 'right';
2730 } else {
2731 $farside = 'right';
2732 $nearside = 'left';
2733 }
2734 return "<div class=\"editsection\" style=\"float:$farside;margin-$nearside:5px;\">[".$url."]</div>";
2735
2736 }
2737
2738 // This function is called by EditPage.php and shows a bulletin board style
2739 // toolbar for common editing functions. It can be disabled in the user preferences.
2740 // The necsesary JavaScript code can be found in style/wikibits.js.
2741 function getEditToolbar() {
2742 global $wgStylePath, $wgLang, $wgMimeType;
2743
2744 // toolarray an array of arrays which each include the filename of
2745 // the button image (without path), the opening tag, the closing tag,
2746 // and optionally a sample text that is inserted between the two when no
2747 // selection is highlighted.
2748 // The tip text is shown when the user moves the mouse over the button.
2749
2750 // Already here are accesskeys (key), which are not used yet until someone
2751 // can figure out a way to make them work in IE. However, we should make
2752 // sure these keys are not defined on the edit page.
2753 $toolarray=array(
2754 array( 'image'=>'button_bold.png',
2755 'open'=>"\'\'\'",
2756 'close'=>"\'\'\'",
2757 'sample'=>wfMsg('bold_sample'),
2758 'tip'=>wfMsg('bold_tip'),
2759 'key'=>'B'
2760 ),
2761 array( "image"=>"button_italic.png",
2762 "open"=>"\'\'",
2763 "close"=>"\'\'",
2764 "sample"=>wfMsg("italic_sample"),
2765 "tip"=>wfMsg("italic_tip"),
2766 "key"=>"I"
2767 ),
2768 array( "image"=>"button_link.png",
2769 "open"=>"[[",
2770 "close"=>"]]",
2771 "sample"=>wfMsg("link_sample"),
2772 "tip"=>wfMsg("link_tip"),
2773 "key"=>"L"
2774 ),
2775 array( "image"=>"button_extlink.png",
2776 "open"=>"[",
2777 "close"=>"]",
2778 "sample"=>wfMsg("extlink_sample"),
2779 "tip"=>wfMsg("extlink_tip"),
2780 "key"=>"X"
2781 ),
2782 array( "image"=>"button_headline.png",
2783 "open"=>"\\n== ",
2784 "close"=>" ==\\n",
2785 "sample"=>wfMsg("headline_sample"),
2786 "tip"=>wfMsg("headline_tip"),
2787 "key"=>"H"
2788 ),
2789 array( "image"=>"button_image.png",
2790 "open"=>"[[".$wgLang->getNsText(NS_IMAGE).":",
2791 "close"=>"]]",
2792 "sample"=>wfMsg("image_sample"),
2793 "tip"=>wfMsg("image_tip"),
2794 "key"=>"D"
2795 ),
2796 array( "image"=>"button_media.png",
2797 "open"=>"[[".$wgLang->getNsText(NS_MEDIA).":",
2798 "close"=>"]]",
2799 "sample"=>wfMsg("media_sample"),
2800 "tip"=>wfMsg("media_tip"),
2801 "key"=>"M"
2802 ),
2803 array( "image"=>"button_math.png",
2804 "open"=>"\\<math\\>",
2805 "close"=>"\\</math\\>",
2806 "sample"=>wfMsg("math_sample"),
2807 "tip"=>wfMsg("math_tip"),
2808 "key"=>"C"
2809 ),
2810 array( "image"=>"button_nowiki.png",
2811 "open"=>"\\<nowiki\\>",
2812 "close"=>"\\</nowiki\\>",
2813 "sample"=>wfMsg("nowiki_sample"),
2814 "tip"=>wfMsg("nowiki_tip"),
2815 "key"=>"N"
2816 ),
2817 array( "image"=>"button_sig.png",
2818 "open"=>"--~~~~",
2819 "close"=>"",
2820 "sample"=>"",
2821 "tip"=>wfMsg("sig_tip"),
2822 "key"=>"Y"
2823 ),
2824 array( "image"=>"button_hr.png",
2825 "open"=>"\\n----\\n",
2826 "close"=>"",
2827 "sample"=>"",
2828 "tip"=>wfMsg("hr_tip"),
2829 "key"=>"R"
2830 )
2831 );
2832 $toolbar ="<script type='text/javascript'>\n/*<![CDATA[*/\n";
2833
2834 $toolbar.="document.writeln(\"<div id='toolbar'>\");\n";
2835 foreach($toolarray as $tool) {
2836
2837 $image=$wgStylePath.'/images/'.$tool['image'];
2838 $open=$tool['open'];
2839 $close=$tool['close'];
2840 $sample = addslashes( $tool['sample'] );
2841
2842 // Note that we use the tip both for the ALT tag and the TITLE tag of the image.
2843 // Older browsers show a "speedtip" type message only for ALT.
2844 // Ideally these should be different, realistically they
2845 // probably don't need to be.
2846 $tip = addslashes( $tool['tip'] );
2847
2848 #$key = $tool["key"];
2849
2850 $toolbar.="addButton('$image','$tip','$open','$close','$sample');\n";
2851 }
2852
2853 $toolbar.="addInfobox('" . addslashes( wfMsg( "infobox" ) ) . "','" . addslashes(wfMsg("infobox_alert")) . "');\n";
2854 $toolbar.="document.writeln(\"</div>\");\n";
2855
2856 $toolbar.="/*]]>*/\n</script>";
2857 return $toolbar;
2858 }
2859
2860 /* public */ function suppressUrlExpansion() {
2861 return false;
2862 }
2863 }
2864
2865 }
2866 ?>