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