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