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