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